From a19ed46b2a55dc93e5792c84e57a7c45b89f97a0 Mon Sep 17 00:00:00 2001 From: Exzap <13877693+Exzap@users.noreply.github.com> Date: Fri, 14 Oct 2022 12:49:41 +0200 Subject: [PATCH 001/589] Windows: Fix file and folder dialog freeze (#369) Initializing the COM library immediately seems to be more robust than doing it on demand --- src/audio/CubebAPI.cpp | 18 ------------------ src/audio/CubebAPI.h | 1 - src/audio/XAudio27API.cpp | 9 --------- src/audio/XAudio27API.h | 1 - src/audio/XAudio2API.cpp | 14 -------------- src/audio/XAudio2API.h | 1 - src/main.cpp | 10 +++++++--- 7 files changed, 7 insertions(+), 47 deletions(-) diff --git a/src/audio/CubebAPI.cpp b/src/audio/CubebAPI.cpp index c40e0f55..8b2a235f 100644 --- a/src/audio/CubebAPI.cpp +++ b/src/audio/CubebAPI.cpp @@ -167,25 +167,11 @@ void CubebAPI::SetVolume(sint32 volume) bool CubebAPI::InitializeStatic() { -#if BOOST_OS_WINDOWS - s_com_initialized = (SUCCEEDED(CoInitializeEx(nullptr, COINIT_MULTITHREADED))); -#endif - if (cubeb_init(&s_context, "Cemu Cubeb", nullptr)) { cemuLog_force("can't create cubeb audio api"); - -#if BOOST_OS_WINDOWS - if (s_com_initialized) - { - CoUninitialize(); - s_com_initialized = false; - } -#endif - return false; } - return true; } @@ -193,10 +179,6 @@ void CubebAPI::Destroy() { if (s_context) cubeb_destroy(s_context); -#if BOOST_OS_WINDOWS - if (s_com_initialized) - CoUninitialize(); -#endif } std::vector CubebAPI::GetDevices() diff --git a/src/audio/CubebAPI.h b/src/audio/CubebAPI.h index a828ce0d..2dce9374 100644 --- a/src/audio/CubebAPI.h +++ b/src/audio/CubebAPI.h @@ -41,7 +41,6 @@ public: static void Destroy(); private: - inline static bool s_com_initialized = false; inline static cubeb* s_context = nullptr; cubeb_stream* m_stream = nullptr; diff --git a/src/audio/XAudio27API.cpp b/src/audio/XAudio27API.cpp index 4a99bfa2..fadd02f8 100644 --- a/src/audio/XAudio27API.cpp +++ b/src/audio/XAudio27API.cpp @@ -5,7 +5,6 @@ static_assert(IAudioAPI::kBlockCount < XAUDIO2_MAX_QUEUED_BUFFERS, "too many xaudio2 buffers"); HMODULE XAudio27API::s_xaudio_dll = nullptr; -bool XAudio27API::s_com_initialized = false; std::unique_ptr XAudio27API::s_xaudio; XAudio27API::XAudio27API(uint32 device_id, uint32 samplerate, uint32 channels, uint32 samples_per_block, uint32 bits_per_sample) @@ -115,8 +114,6 @@ bool XAudio27API::InitializeStatic() if (s_xaudio) return true; - s_com_initialized = (SUCCEEDED(CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE))); - #ifdef _DEBUG s_xaudio_dll = LoadLibraryExW(L"XAudioD2_7.DLL", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); if(!s_xaudio_dll) @@ -142,9 +139,6 @@ bool XAudio27API::InitializeStatic() if (s_xaudio_dll) FreeLibrary(s_xaudio_dll); - if (s_com_initialized) - CoUninitialize(); - return false; } } @@ -155,9 +149,6 @@ void XAudio27API::Destroy() if (s_xaudio_dll) FreeLibrary(s_xaudio_dll); - - if (s_com_initialized) - CoUninitialize(); } std::vector XAudio27API::GetDevices() diff --git a/src/audio/XAudio27API.h b/src/audio/XAudio27API.h index 80e423a3..badab8f6 100644 --- a/src/audio/XAudio27API.h +++ b/src/audio/XAudio27API.h @@ -58,7 +58,6 @@ private: }; static HMODULE s_xaudio_dll; - static bool s_com_initialized; static std::unique_ptr s_xaudio; std::unique_ptr m_xaudio; diff --git a/src/audio/XAudio2API.cpp b/src/audio/XAudio2API.cpp index fd0a305b..9759210d 100644 --- a/src/audio/XAudio2API.cpp +++ b/src/audio/XAudio2API.cpp @@ -23,7 +23,6 @@ static const GUID DEVINTERFACE_AUDIO_RENDER_GUID = { 0xe6327cad, 0xdcec, 0x4949, static_assert(IAudioAPI::kBlockCount < XAUDIO2_MAX_QUEUED_BUFFERS, "too many xaudio2 buffers"); HMODULE XAudio2API::s_xaudio_dll = nullptr; -bool XAudio2API::s_com_initialized = false; std::vector XAudio2API::s_devices; XAudio2API::XAudio2API(std::wstring device_id, uint32 samplerate, uint32 channels, uint32 samples_per_block, uint32 bits_per_sample) @@ -143,8 +142,6 @@ bool XAudio2API::InitializeStatic() { if (s_xaudio_dll) return true; - - s_com_initialized = (SUCCEEDED(CoInitializeEx(nullptr, COINIT_MULTITHREADED))); // win 10 s_xaudio_dll = LoadLibraryEx(XAUDIO2_DLL, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); @@ -166,9 +163,6 @@ bool XAudio2API::InitializeStatic() if (s_xaudio_dll) FreeLibrary(s_xaudio_dll); - if (s_com_initialized) - CoUninitialize(); - return false; } } @@ -177,20 +171,12 @@ void XAudio2API::Destroy() { if (s_xaudio_dll) FreeLibrary(s_xaudio_dll); - - if (s_com_initialized) - CoUninitialize(); } const std::vector& XAudio2API::RefreshDevices() { - // this function must be called from the same thread as we called CoInitializeEx s_devices.clear(); - HRESULT r = CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE); - if (r != RPC_E_CHANGED_MODE && FAILED(r)) - return s_devices; - try { struct IWbemLocator *wbem_locator = nullptr; diff --git a/src/audio/XAudio2API.h b/src/audio/XAudio2API.h index 2b23e1cc..1f7057f0 100644 --- a/src/audio/XAudio2API.h +++ b/src/audio/XAudio2API.h @@ -59,7 +59,6 @@ private: }; static HMODULE s_xaudio_dll; - static bool s_com_initialized; static std::vector s_devices; std::unique_ptr m_xaudio; diff --git a/src/main.cpp b/src/main.cpp index e1c8ca49..323494c1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -323,10 +323,10 @@ void HandlePostUpdate() fs::remove(filename, ec); } #else - while( fs::exists(filename) ) + while (fs::exists(filename)) { std::error_code ec; - fs::remove(filename, ec); + fs::remove(filename, ec); std::this_thread::sleep_for(std::chrono::milliseconds(1000)); } #endif @@ -338,8 +338,10 @@ void ToolShaderCacheMerger(); #if BOOST_OS_WINDOWS // entrypoint for release builds -int wWinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPTSTR lpCmdLine, _In_ int nShowCmd) +int wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPTSTR lpCmdLine, _In_ int nShowCmd) { + if (FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE))) + cemuLog_log(LogType::Force, "CoInitializeEx() failed"); SDL_SetMainReady(); if (!LaunchSettings::HandleCommandline(lpCmdLine)) return 0; @@ -350,6 +352,8 @@ int wWinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ L // entrypoint for debug builds with console int main(int argc, char* argv[]) { + if (FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE))) + cemuLog_log(LogType::Force, "CoInitializeEx() failed"); SDL_SetMainReady(); if (!LaunchSettings::HandleCommandline(argc, argv)) return 0; From ada8bbb3b49622e19deccb7358b1c804a766baab Mon Sep 17 00:00:00 2001 From: Exzap <13877693+Exzap@users.noreply.github.com> Date: Fri, 14 Oct 2022 13:45:40 +0200 Subject: [PATCH 002/589] Linux/MacOS: Greatly improve performance (#370) std::unordered_set is implemented as a flat hashtable on libstdc++ which makes clearing expensive due to invoking memset on the entire table. To get the best performance across all platforms this replaces the unordered_set with a custom high-performance sparse bitset --- src/Cafe/HW/Latte/Core/LatteBufferCache.cpp | 73 ++++++++++++++++++--- 1 file changed, 65 insertions(+), 8 deletions(-) diff --git a/src/Cafe/HW/Latte/Core/LatteBufferCache.cpp b/src/Cafe/HW/Latte/Core/LatteBufferCache.cpp index a70ff888..1e2c43b1 100644 --- a/src/Cafe/HW/Latte/Core/LatteBufferCache.cpp +++ b/src/Cafe/HW/Latte/Core/LatteBufferCache.cpp @@ -1005,8 +1005,67 @@ void LatteBufferCache_getStats(uint32& heapSize, uint32& allocationSize, uint32& } FSpinlock g_spinlockDCFlushQueue; -std::unordered_set* g_DCFlushQueue = new std::unordered_set(); // queued pages -std::unordered_set* g_DCFlushQueueAlternate = new std::unordered_set(); + +class SparseBitset +{ + static inline constexpr size_t TABLE_MASK = 0xFF; + +public: + bool Empty() const + { + return m_numNonEmptyVectors == 0; + } + + void Set(uint32 index) + { + auto& v = m_bits[index & TABLE_MASK]; + if (std::find(v.cbegin(), v.cend(), index) != v.end()) + return; + if (v.empty()) + { + m_nonEmptyVectors[m_numNonEmptyVectors] = &v; + m_numNonEmptyVectors++; + } + v.emplace_back(index); + } + + template + void ForAllAndClear(TFunc callbackFunc) + { + auto vCurrent = m_nonEmptyVectors + 0; + auto vEnd = m_nonEmptyVectors + m_numNonEmptyVectors; + while (vCurrent < vEnd) + { + std::vector* vec = *vCurrent; + vCurrent++; + for (const auto& it : *vec) + callbackFunc(it); + vec->clear(); + } + m_numNonEmptyVectors = 0; + } + + void Clear() + { + auto vCurrent = m_nonEmptyVectors + 0; + auto vEnd = m_nonEmptyVectors + m_numNonEmptyVectors; + while (vCurrent < vEnd) + { + std::vector* vec = *vCurrent; + vCurrent++; + vec->clear(); + } + m_numNonEmptyVectors = 0; + } + +private: + std::vector m_bits[TABLE_MASK + 1]; + std::vector* m_nonEmptyVectors[TABLE_MASK + 1]; + size_t m_numNonEmptyVectors{ 0 }; +}; + +SparseBitset* s_DCFlushQueue = new SparseBitset(); +SparseBitset* s_DCFlushQueueAlternate = new SparseBitset(); void LatteBufferCache_notifyDCFlush(MPTR address, uint32 size) { @@ -1017,20 +1076,18 @@ void LatteBufferCache_notifyDCFlush(MPTR address, uint32 size) uint32 lastPage = (address + size - 1) / CACHE_PAGE_SIZE; g_spinlockDCFlushQueue.acquire(); for (uint32 i = firstPage; i <= lastPage; i++) - g_DCFlushQueue->emplace(i); + s_DCFlushQueue->Set(i); g_spinlockDCFlushQueue.release(); } void LatteBufferCache_processDCFlushQueue() { - if (g_DCFlushQueue->empty()) // accessing this outside of the lock is technically undefined/unsafe behavior but on all known implementations this is fine and we can avoid the spinlock + if (s_DCFlushQueue->Empty()) // quick check to avoid locking if there is no work to do return; g_spinlockDCFlushQueue.acquire(); - std::swap(g_DCFlushQueue, g_DCFlushQueueAlternate); + std::swap(s_DCFlushQueue, s_DCFlushQueueAlternate); g_spinlockDCFlushQueue.release(); - for (auto& itr : *g_DCFlushQueueAlternate) - LatteBufferCache_invalidatePage(itr * CACHE_PAGE_SIZE); - g_DCFlushQueueAlternate->clear(); + s_DCFlushQueueAlternate->ForAllAndClear([](uint32 index) {LatteBufferCache_invalidatePage(index * CACHE_PAGE_SIZE); }); } void LatteBufferCache_notifyDrawDone() From df0e2f78818d662b90839fa46c7441777f07003c Mon Sep 17 00:00:00 2001 From: Tillsunset <35825944+Tillsunset@users.noreply.github.com> Date: Sat, 15 Oct 2022 00:20:20 -0500 Subject: [PATCH 003/589] Fix Cannot set locale to "" (#366) * Add en resource and change language selection for macos user that don't have US as their system region * default to English if the system language is unavailable --- bin/resources/en/cemu.mo | Bin 0 -> 56624 bytes src/gui/CemuApp.cpp | 20 +++++++++++--------- 2 files changed, 11 insertions(+), 9 deletions(-) create mode 100644 bin/resources/en/cemu.mo diff --git a/bin/resources/en/cemu.mo b/bin/resources/en/cemu.mo new file mode 100644 index 0000000000000000000000000000000000000000..93d8f7e59bd0864234171af1e3ba46ba15c562c8 GIT binary patch literal 56624 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 literal 0 HcmV?d00001 diff --git a/src/gui/CemuApp.cpp b/src/gui/CemuApp.cpp index 2c766f5b..c7a5adaa 100644 --- a/src/gui/CemuApp.cpp +++ b/src/gui/CemuApp.cpp @@ -115,22 +115,24 @@ bool CemuApp::OnInit() m_languages = GetAvailableLanguages(); const sint32 language = GetConfig().language; - if (language != wxLANGUAGE_ENGLISH) + const auto it = std::find_if(m_languages.begin(), m_languages.end(), [language](const wxLanguageInfo* info) { return info->Language == language; }); + if (it != m_languages.end() && wxLocale::IsAvailable(language)) { - const auto it = std::find_if(m_languages.begin(), m_languages.end(), [language](const wxLanguageInfo* info) { return info->Language == language; }); - if (it != m_languages.end() && wxLocale::IsAvailable(language)) + if (m_locale.Init(language)) { - if (m_locale.Init(language)) - { - m_locale.AddCatalogLookupPathPrefix(ActiveSettings::GetDataPath("resources").generic_string()); - m_locale.AddCatalog("cemu"); - } + m_locale.AddCatalogLookupPathPrefix(ActiveSettings::GetDataPath("resources").generic_string()); + m_locale.AddCatalog("cemu"); } } if (!m_locale.IsOk()) { - m_locale.Init(wxLANGUAGE_DEFAULT); + if (!wxLocale::IsAvailable(wxLANGUAGE_DEFAULT) || !m_locale.Init(wxLANGUAGE_DEFAULT)) + { + m_locale.Init(wxLANGUAGE_ENGLISH); + m_locale.AddCatalogLookupPathPrefix(ActiveSettings::GetDataPath("resources").generic_string()); + m_locale.AddCatalog("cemu"); + } } // fill colour db From f0938e1a23f6cdd03bfd1e21d84f2c0f65aeb45f Mon Sep 17 00:00:00 2001 From: Tillsunset <35825944+Tillsunset@users.noreply.github.com> Date: Sat, 15 Oct 2022 06:38:06 -0500 Subject: [PATCH 004/589] Fix CRC errors on MacOS(/Linux?) (#375) Fixes graphic packs (like FPS++) not working even when enabled. --- src/util/crypto/crc32.cpp | 51 +++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/src/util/crypto/crc32.cpp b/src/util/crypto/crc32.cpp index f6e88165..65c6a8f8 100644 --- a/src/util/crypto/crc32.cpp +++ b/src/util/crypto/crc32.cpp @@ -322,29 +322,34 @@ unsigned int crc32_calc_slice_by_8(unsigned int previousCrc32, const void* data, // process eight bytes at once (Slicing-by-8) while (length >= 8) { -#if __BYTE_ORDER == __BIG_ENDIAN - uint32_t one = *current++ ^ swap(crc); - uint32_t two = *current++; - crc = Crc32Lookup[0][two & 0xFF] ^ - Crc32Lookup[1][(two >> 8) & 0xFF] ^ - Crc32Lookup[2][(two >> 16) & 0xFF] ^ - Crc32Lookup[3][(two >> 24) & 0xFF] ^ - Crc32Lookup[4][one & 0xFF] ^ - Crc32Lookup[5][(one >> 8) & 0xFF] ^ - Crc32Lookup[6][(one >> 16) & 0xFF] ^ - Crc32Lookup[7][(one >> 24) & 0xFF]; -#else - uint32_t one = *current++ ^ crc; - uint32_t two = *current++; - crc = Crc32Lookup[0][(two >> 24) & 0xFF] ^ - Crc32Lookup[1][(two >> 16) & 0xFF] ^ - Crc32Lookup[2][(two >> 8) & 0xFF] ^ - Crc32Lookup[3][two & 0xFF] ^ - Crc32Lookup[4][(one >> 24) & 0xFF] ^ - Crc32Lookup[5][(one >> 16) & 0xFF] ^ - Crc32Lookup[6][(one >> 8) & 0xFF] ^ - Crc32Lookup[7][one & 0xFF]; -#endif + if constexpr (std::endian::native == std::endian::big){ + uint32_t one = *current++ ^ swap(crc); + uint32_t two = *current++; + crc = Crc32Lookup[0][two & 0xFF] ^ + Crc32Lookup[1][(two >> 8) & 0xFF] ^ + Crc32Lookup[2][(two >> 16) & 0xFF] ^ + Crc32Lookup[3][(two >> 24) & 0xFF] ^ + Crc32Lookup[4][one & 0xFF] ^ + Crc32Lookup[5][(one >> 8) & 0xFF] ^ + Crc32Lookup[6][(one >> 16) & 0xFF] ^ + Crc32Lookup[7][(one >> 24) & 0xFF]; + } + else if constexpr (std::endian::native == std::endian::little) + { + uint32_t one = *current++ ^ crc; + uint32_t two = *current++; + crc = Crc32Lookup[0][(two >> 24) & 0xFF] ^ + Crc32Lookup[1][(two >> 16) & 0xFF] ^ + Crc32Lookup[2][(two >> 8) & 0xFF] ^ + Crc32Lookup[3][two & 0xFF] ^ + Crc32Lookup[4][(one >> 24) & 0xFF] ^ + Crc32Lookup[5][(one >> 16) & 0xFF] ^ + Crc32Lookup[6][(one >> 8) & 0xFF] ^ + Crc32Lookup[7][one & 0xFF]; + } + else { + cemu_assert(false); + } length -= 8; } From e88d20cbfbada6b1d144c4944f080f70299c1506 Mon Sep 17 00:00:00 2001 From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com> Date: Sun, 16 Oct 2022 09:02:33 +0200 Subject: [PATCH 005/589] Fix crashes when wxWidgets tries to free stack allocated dialogs (#377) --- src/gui/MainWindow.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 5ebfe09d..3291f3bb 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -763,7 +763,6 @@ void MainWindow::OpenSettings() frame.ShowModal(); const bool paths_modified = frame.ShouldReloadGamelist(); const bool mlc_modified = frame.MLCModified(); - frame.Destroy(); if (paths_modified) m_game_list->ReloadGameEntries(false); @@ -1722,7 +1721,6 @@ void MainWindow::OnTimer(wxTimerEvent& event) { CemuUpdateWindow update_window(this); update_window.ShowModal(); - update_window.Destroy(); } } @@ -1999,7 +1997,6 @@ void MainWindow::OnHelpUpdate(wxCommandEvent& event) { CemuUpdateWindow test(this); test.ShowModal(); - test.Destroy(); } void MainWindow::OnHelpGettingStarted(wxCommandEvent& event) From 753040f73a8700d53bb742d33e428e060308bb20 Mon Sep 17 00:00:00 2001 From: MythicalPlayz <57963367+MythicalPlayz@users.noreply.github.com> Date: Mon, 17 Oct 2022 11:26:32 +0200 Subject: [PATCH 006/589] Added Boot Image for Gamepad (#372) --- src/Cafe/HW/Latte/Core/LatteShaderCache.cpp | 119 +++++++++++++++++--- 1 file changed, 103 insertions(+), 16 deletions(-) diff --git a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp index ba85898c..c8299032 100644 --- a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp +++ b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp @@ -43,7 +43,8 @@ struct struct { - ImTextureID textureId; + ImTextureID textureTVId; + ImTextureID textureDRCId; // shader loading sint32 loadedShaderFiles; sint32 shaderFileCount; @@ -230,12 +231,12 @@ void LatteShaderCache_load() g_shaderCacheLoaderState.loadedShaderFiles = 0; // get game background loading image - TGAFILE file{}; - g_shaderCacheLoaderState.textureId = nullptr; + TGAFILE TVfile{}; + g_shaderCacheLoaderState.textureTVId = nullptr; std::string tvTexPath = fmt::format("{}/meta/bootTvTex.tga", CafeSystem::GetMlcStoragePath(CafeSystem::GetForegroundTitleId())); - sint32 status; - auto fscfile = fsc_open(tvTexPath.c_str(), FSC_ACCESS_FLAG::OPEN_FILE | FSC_ACCESS_FLAG::READ_PERMISSION, &status); + sint32 statusTV; + auto fscfile = fsc_open(tvTexPath.c_str(), FSC_ACCESS_FLAG::OPEN_FILE | FSC_ACCESS_FLAG::READ_PERMISSION, &statusTV); if (fscfile) { uint32 size = fsc_getFileSize(fscfile); @@ -243,15 +244,35 @@ void LatteShaderCache_load() { std::vector tmpData(size); fsc_readFile(fscfile, tmpData.data(), size); - const bool backgroundLoaded = LoadTGAFile(tmpData, &file); + const bool backgroundLoaded = LoadTGAFile(tmpData, &TVfile); if (backgroundLoaded) - g_shaderCacheLoaderState.textureId = g_renderer->GenerateTexture(file.imageData, { file.imageWidth, file.imageHeight }); + g_shaderCacheLoaderState.textureTVId = g_renderer->GenerateTexture(TVfile.imageData, { TVfile.imageWidth, TVfile.imageHeight }); } fsc_close(fscfile); } + //get game background loading image for DRC + TGAFILE DRCfile{}; + g_shaderCacheLoaderState.textureDRCId = nullptr; + std::string drcTexPath = fmt::format("{}/meta/bootDRCTex.tga", CafeSystem::GetMlcStoragePath(CafeSystem::GetForegroundTitleId())); + sint32 statusDRC; + auto fscfile2 = fsc_open(drcTexPath.c_str(), FSC_ACCESS_FLAG::OPEN_FILE | FSC_ACCESS_FLAG::READ_PERMISSION, &statusDRC); + if (fscfile2) + { + uint32 size = fsc_getFileSize(fscfile2); + if (size > 0) + { + std::vector tmpData(size); + fsc_readFile(fscfile2, tmpData.data(), size); + const bool backgroundLoaded = LoadTGAFile(tmpData, &DRCfile); + + if (backgroundLoaded) + g_shaderCacheLoaderState.textureDRCId = g_renderer->GenerateTexture(DRCfile.imageData, { DRCfile.imageWidth, DRCfile.imageHeight }); + } + fsc_close(fscfile2); + } sint32 numLoadedShaders = 0; uint32 loadIndex = 0; @@ -312,7 +333,7 @@ void LatteShaderCache_load() ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0,0 }); if (ImGui::Begin("Background texture", nullptr, kPopupFlags)) { - if (g_shaderCacheLoaderState.textureId) + if (g_shaderCacheLoaderState.textureTVId) { float imageDisplayWidth = io.DisplaySize.x; float imageDisplayHeight = 720 * imageDisplayWidth / 1280; @@ -327,19 +348,54 @@ void LatteShaderCache_load() paddingTopAndBottom = 0.0f; } - ImGui::GetWindowDrawList()->AddImage(g_shaderCacheLoaderState.textureId, ImVec2(paddingLeftAndRight, paddingTopAndBottom), ImVec2(io.DisplaySize.x-paddingLeftAndRight, io.DisplaySize.y-paddingTopAndBottom), { 0,1 }, { 1,0 }); + ImGui::GetWindowDrawList()->AddImage(g_shaderCacheLoaderState.textureTVId, ImVec2(paddingLeftAndRight, paddingTopAndBottom), ImVec2(io.DisplaySize.x-paddingLeftAndRight, io.DisplaySize.y-paddingTopAndBottom), { 0,1 }, { 1,0 }); } ImGui::End(); + ImGui::PopStyleVar(2); + g_renderer->ImguiEnd(); } - ImGui::PopStyleVar(2); - - g_renderer->ImguiEnd(); } + + g_renderer->BeginFrame(false); + if (g_renderer->ImguiBegin(false)) + { + ImGui::SetNextWindowPos({ 0,0 }, ImGuiCond_Always); + ImGui::SetNextWindowSize(io.DisplaySize, ImGuiCond_Always); + ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0,0 }); + + if (ImGui::Begin("Background texture2", nullptr, kPopupFlags)) + { + if (g_shaderCacheLoaderState.textureDRCId) + { + float imageDisplayWidth = io.DisplaySize.x; + float imageDisplayHeight = 480 * imageDisplayWidth / 854; + + float paddingLeftAndRight = 0.0f; + float paddingTopAndBottom = (io.DisplaySize.y - imageDisplayHeight)/2.0f; + if (imageDisplayHeight > io.DisplaySize.y) + { + imageDisplayHeight = io.DisplaySize.y; + imageDisplayWidth = 854 * imageDisplayHeight / 480; + paddingLeftAndRight = (io.DisplaySize.x - imageDisplayWidth)/2.0f; + paddingTopAndBottom = 0.0f; + } + + ImGui::GetWindowDrawList()->AddImage(g_shaderCacheLoaderState.textureDRCId, ImVec2(paddingLeftAndRight, paddingTopAndBottom), ImVec2(io.DisplaySize.x-paddingLeftAndRight, io.DisplaySize.y-paddingTopAndBottom), { 0,1 }, { 1,0 }); + } + ImGui::End(); + ImGui::PopStyleVar(2); + g_renderer->ImguiEnd(); + } + } + g_renderer->SwapBuffers(true, true); } - if (g_shaderCacheLoaderState.textureId) - g_renderer->DeleteTexture(g_shaderCacheLoaderState.textureId); + if (g_shaderCacheLoaderState.textureTVId) + g_renderer->DeleteTexture(g_shaderCacheLoaderState.textureTVId); + if (g_shaderCacheLoaderState.textureDRCId) + g_renderer->DeleteTexture(g_shaderCacheLoaderState.textureDRCId); } void LatteShaderCache_ShowProgress(const std::function & loadUpdateFunc, bool isPipelines) @@ -374,7 +430,7 @@ void LatteShaderCache_ShowProgress(const std::function & loadUpdateF const auto progress_font = ImGui_GetFont(window_size.y / 32.0f); // = 24 by default const auto shader_count_font = ImGui_GetFont(window_size.y / 48.0f); // = 16 // render background texture - if (g_shaderCacheLoaderState.textureId) + if (g_shaderCacheLoaderState.textureTVId) { ImGui::SetNextWindowPos({ 0, 0 }, ImGuiCond_Always); ImGui::SetNextWindowSize(io.DisplaySize, ImGuiCond_Always); @@ -395,7 +451,7 @@ void LatteShaderCache_ShowProgress(const std::function & loadUpdateF paddingTopAndBottom = 0.0f; } - ImGui::GetWindowDrawList()->AddImage(g_shaderCacheLoaderState.textureId, ImVec2(paddingLeftAndRight, paddingTopAndBottom), ImVec2(io.DisplaySize.x-paddingLeftAndRight, io.DisplaySize.y-paddingTopAndBottom), { 0,1 }, { 1,0 }); + ImGui::GetWindowDrawList()->AddImage(g_shaderCacheLoaderState.textureTVId, ImVec2(paddingLeftAndRight, paddingTopAndBottom), ImVec2(io.DisplaySize.x-paddingLeftAndRight, io.DisplaySize.y-paddingTopAndBottom), { 0,1 }, { 1,0 }); ImGui::End(); } ImGui::PopStyleVar(2); @@ -484,6 +540,37 @@ void LatteShaderCache_ShowProgress(const std::function & loadUpdateF lastFrameUpdate = tick_cached(); } + g_renderer->BeginFrame(false); + if (g_renderer->ImguiBegin(false)) + { + ImGui::SetNextWindowPos({ 0,0 }, ImGuiCond_Always); + ImGui::SetNextWindowSize(io.DisplaySize, ImGuiCond_Always); + ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0,0 }); + if (ImGui::Begin("Background texture2", nullptr, kPopupFlags)) + { + if (g_shaderCacheLoaderState.textureDRCId) + { + float imageDisplayWidth = io.DisplaySize.x; + float imageDisplayHeight = 480 * imageDisplayWidth / 854; + + float paddingLeftAndRight = 0.0f; + float paddingTopAndBottom = (io.DisplaySize.y - imageDisplayHeight)/2.0f; + if (imageDisplayHeight > io.DisplaySize.y) + { + imageDisplayHeight = io.DisplaySize.y; + imageDisplayWidth = 854 * imageDisplayHeight / 480; + paddingLeftAndRight = (io.DisplaySize.x - imageDisplayWidth)/2.0f; + paddingTopAndBottom = 0.0f; + } + ImGui::GetWindowDrawList()->AddImage(g_shaderCacheLoaderState.textureDRCId, ImVec2(paddingLeftAndRight, paddingTopAndBottom), ImVec2(io.DisplaySize.x-paddingLeftAndRight, io.DisplaySize.y-paddingTopAndBottom), { 0,1 }, { 1,0 }); + } + ImGui::End(); + ImGui::PopStyleVar(2); + g_renderer->ImguiEnd(); + } + } + // finish frame g_renderer->SwapBuffers(true, true); } From 665a34e51847061e31398a04506dcf2f53dd15f9 Mon Sep 17 00:00:00 2001 From: Exzap <13877693+Exzap@users.noreply.github.com> Date: Mon, 17 Oct 2022 13:25:49 +0200 Subject: [PATCH 007/589] Linux: Always use libpng from system (#381) * Always use system libpng on Linux * Remove dependency on boost-crc in DSU (reuse existing implementation) --- src/input/api/DSU/DSUMessages.cpp | 13 ++----------- src/main.cpp | 2 ++ src/util/crypto/crc32.cpp | 9 +++++++++ src/util/crypto/crc32.h | 7 ++++++- vcpkg.json | 8 +++++--- 5 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/input/api/DSU/DSUMessages.cpp b/src/input/api/DSU/DSUMessages.cpp index d0ea61af..f92c1e3f 100644 --- a/src/input/api/DSU/DSUMessages.cpp +++ b/src/input/api/DSU/DSUMessages.cpp @@ -1,6 +1,5 @@ #include "input/api/DSU/DSUMessages.h" - -#include +#include "util/crypto/crc32.h" constexpr uint32_t kMagicClient = 'CUSD'; constexpr uint32_t kMagicServer = 'SUSD'; @@ -17,15 +16,7 @@ void MessageHeader::Finalize(size_t size) uint32_t MessageHeader::CRC32(size_t size) const { - const auto tmp = m_crc32; - m_crc32 = 0; - - boost::crc_32_type crc; - crc.process_bytes(this, size); - const auto result = crc.checksum(); - - m_crc32 = tmp; - return result; + return crc32_calc(this, size); } bool MessageHeader::IsClientMessage() const { return m_magic == kMagicClient; } diff --git a/src/main.cpp b/src/main.cpp index 323494c1..801683d1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -234,6 +234,7 @@ void ppcAsmTest(); void gx2CopySurfaceTest(); void ExpressionParser_test(); void FSTVolumeTest(); +void CRCTest(); void unitTests() { @@ -241,6 +242,7 @@ void unitTests() gx2CopySurfaceTest(); ppcAsmTest(); FSTVolumeTest(); + CRCTest(); } int mainEmulatorHLE() diff --git a/src/util/crypto/crc32.cpp b/src/util/crypto/crc32.cpp index 65c6a8f8..52eb8a88 100644 --- a/src/util/crypto/crc32.cpp +++ b/src/util/crypto/crc32.cpp @@ -382,4 +382,13 @@ unsigned int crc32_calc(unsigned int c, const void* data, int length) p++; } return ~c; +} + +void CRCTest() +{ + std::vector testData; + for (uint8 i = 0; i < 89; i++) + testData.emplace_back(i); + uint32 r = crc32_calc(0, testData.data(), testData.size()); + cemu_assert(r == 0x3fc61683); } \ No newline at end of file diff --git a/src/util/crypto/crc32.h b/src/util/crypto/crc32.h index 6a254433..b8002261 100644 --- a/src/util/crypto/crc32.h +++ b/src/util/crypto/crc32.h @@ -1,3 +1,8 @@ #pragma once -unsigned int crc32_calc(unsigned int c, const void* data, int length); \ No newline at end of file +unsigned int crc32_calc(unsigned int c, const void* data, int length); + +inline unsigned int crc32_calc(const void* data, int length) +{ + return crc32_calc(0, data, length); +} \ No newline at end of file diff --git a/vcpkg.json b/vcpkg.json index 33587607..e85a4311 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -5,8 +5,11 @@ "dependencies": [ "pugixml", "zlib", - "libpng", - "zstd", + "zstd", + { + "name": "libpng", + "platform": "!linux" + }, { "name": "libzip", "default-features": false @@ -23,7 +26,6 @@ "boost-dll", "boost-optional", "boost-signals2", - "boost-crc", "boost-asio", "boost-ptr-container", "boost-property-tree", From 15b3a3f77d8c0c6e3a95061ff337d61b198ff665 Mon Sep 17 00:00:00 2001 From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com> Date: Mon, 17 Oct 2022 16:05:35 +0200 Subject: [PATCH 008/589] Linux: Remove libpng dependency from wxwidgets (#382) --- dependencies/vcpkg_overlay_ports/wxwidgets/vcpkg.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dependencies/vcpkg_overlay_ports/wxwidgets/vcpkg.json b/dependencies/vcpkg_overlay_ports/wxwidgets/vcpkg.json index 3f04aece..95b2eea5 100644 --- a/dependencies/vcpkg_overlay_ports/wxwidgets/vcpkg.json +++ b/dependencies/vcpkg_overlay_ports/wxwidgets/vcpkg.json @@ -17,7 +17,10 @@ "platform": "!windows & !osx" }, "expat", - "libpng", + { + "name": "libpng", + "platform": "!linux" + }, "tiff", { "name": "vcpkg-cmake", From 271a4e4719463ece58db74b9c390f83bf6e956cf Mon Sep 17 00:00:00 2001 From: MythicalPlayz <57963367+MythicalPlayz@users.noreply.github.com> Date: Tue, 18 Oct 2022 17:08:09 +0200 Subject: [PATCH 009/589] Fixed Discord Rich Presence not working on games that are on MLC (#383) --- src/Cafe/CafeSystem.cpp | 5 ++- src/gui/MainWindow.cpp | 76 +---------------------------------------- src/gui/MainWindow.h | 1 - 3 files changed, 3 insertions(+), 79 deletions(-) diff --git a/src/Cafe/CafeSystem.cpp b/src/Cafe/CafeSystem.cpp index e2e1c5ef..acfd1d2f 100644 --- a/src/Cafe/CafeSystem.cpp +++ b/src/Cafe/CafeSystem.cpp @@ -704,9 +704,8 @@ namespace CafeSystem std::string GetForegroundTitleName() { if (sLaunchModeIsStandalone) - return "Missing meta data"; - // todo - use language based on Cemu console language - return sGameInfo_ForegroundTitle.GetBase().GetMetaInfo()->GetShortName(CafeConsoleLanguage::EN); + return "Unknown Game"; + return sGameInfo_ForegroundTitle.GetBase().GetMetaInfo()->GetShortName(GetConfig().console_language); } std::string GetForegroundTitleArgStr() diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 3291f3bb..fb18a7de 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -543,8 +543,7 @@ bool MainWindow::FileLoad(std::wstring fileName, wxLaunchGameEvent::INITIATED_BY m_game_list = nullptr; } - const auto game_name = GetGameName(fileName); - m_launched_game_name = boost::nowide::narrow(game_name); + m_launched_game_name = CafeSystem::GetForegroundTitleName(); #ifdef ENABLE_DISCORD_RPC if (m_discord) m_discord->UpdatePresence(DiscordPresence::Playing, m_launched_game_name); @@ -1496,79 +1495,6 @@ void MainWindow::DestroyCanvas() } } - -std::wstring MainWindow::GetGameName(std::wstring_view file_name) -{ - fs::path path{ std::wstring{file_name} }; - const auto extension = path.extension(); - if (extension == ".wud" || extension == ".wux") - { - std::unique_ptr volume(FSTVolume::OpenFromDiscImage(path)); - if (!volume) - return path.filename().generic_wstring(); - - bool foundFile = false; - std::vector metaContent = volume->ExtractFile("meta/meta.xml", &foundFile); - if (!foundFile) - return path.filename().generic_wstring(); - - namespace xml = tinyxml2; - xml::XMLDocument doc; - doc.Parse((const char*)metaContent.data(), metaContent.size()); - - // parse meta.xml - xml::XMLElement* root = doc.FirstChildElement("menu"); - if (root) - { - xml::XMLElement* element = root->FirstChildElement("longname_en"); - if (element) - { - - auto game_name = boost::nowide::widen(element->GetText()); - const auto it = game_name.find(L'\n'); - if (it != std::wstring::npos) - game_name.replace(it, 1, L" - "); - - return game_name; - } - } - return path.filename().generic_wstring(); - } - else if (extension == ".rpx") - { - if (path.has_parent_path() && path.parent_path().has_parent_path()) - { - auto meta_xml = path.parent_path().parent_path() / "meta/meta.xml"; - auto metaXmlData = FileStream::LoadIntoMemory(meta_xml); - if (metaXmlData) - { - namespace xml = tinyxml2; - xml::XMLDocument doc; - if (doc.Parse((const char*)metaXmlData->data(), metaXmlData->size()) == xml::XML_SUCCESS) - { - xml::XMLElement* root = doc.FirstChildElement("menu"); - if (root) - { - xml::XMLElement* element = root->FirstChildElement("longname_en"); - if (element) - { - - auto game_name = boost::nowide::widen(element->GetText()); - const auto it = game_name.find(L'\n'); - if (it != std::wstring::npos) - game_name.replace(it, 1, L" - "); - - return game_name; - } - } - } - } - } - } - - return path.filename().generic_wstring(); -} - void MainWindow::OnSizeEvent(wxSizeEvent& event) { if (!IsMaximized() && !gui_isFullScreen()) diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h index bcf1212d..faf83a99 100644 --- a/src/gui/MainWindow.h +++ b/src/gui/MainWindow.h @@ -130,7 +130,6 @@ public: void CreateCanvas(); void DestroyCanvas(); - std::wstring GetGameName(std::wstring_view file_name); static void ShowCursor(bool state); uintptr_t GetRenderCanvasHWND(); From 9df1325d146a601233c3549c8949d3e1349b6afe Mon Sep 17 00:00:00 2001 From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com> Date: Thu, 20 Oct 2022 13:12:16 +0200 Subject: [PATCH 010/589] Linux: Resolve backtrace symbols directly from .symtab instead of .dynsym (#385) --- src/CMakeLists.txt | 4 - src/Common/CMakeLists.txt | 7 ++ .../ExceptionHandler/ELFSymbolTable.cpp | 108 ++++++++++++++++++ src/Common/ExceptionHandler/ELFSymbolTable.h | 32 ++++++ .../ExceptionHandler_posix.cpp | 47 ++++++-- 5 files changed, 182 insertions(+), 16 deletions(-) create mode 100644 src/Common/ExceptionHandler/ELFSymbolTable.cpp create mode 100644 src/Common/ExceptionHandler/ELFSymbolTable.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 32d6fe60..024432d0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -35,10 +35,6 @@ elseif(UNIX) add_compile_options(-Wno-ambiguous-reversed-operator) endif() - if(NOT APPLE) - add_link_options(-rdynamic) - endif() - add_compile_options(-Wno-multichar -Wno-invalid-offsetof -Wno-switch -Wno-ignored-attributes -Wno-deprecated-enum-enum-conversion) endif() diff --git a/src/Common/CMakeLists.txt b/src/Common/CMakeLists.txt index ca7ea238..7e5825f1 100644 --- a/src/Common/CMakeLists.txt +++ b/src/Common/CMakeLists.txt @@ -43,6 +43,13 @@ PRIVATE ) endif() +if(UNIX AND NOT APPLE) + target_sources(CemuCommon PRIVATE + ExceptionHandler/ELFSymbolTable.cpp + ExceptionHandler/ELFSymbolTable.h + ) +endif() + # All the targets wanting to use the precompiled.h header # have to link to CemuCommon target_precompile_headers(CemuCommon PUBLIC precompiled.h) diff --git a/src/Common/ExceptionHandler/ELFSymbolTable.cpp b/src/Common/ExceptionHandler/ELFSymbolTable.cpp new file mode 100644 index 00000000..0f297bdd --- /dev/null +++ b/src/Common/ExceptionHandler/ELFSymbolTable.cpp @@ -0,0 +1,108 @@ +#include "Common/ExceptionHandler/ELFSymbolTable.h" +#include "Common/FileStream.h" +#include +#include + +uint16 ELFSymbolTable::FindSection(int type, const std::string_view& name) +{ + if (!shTable || !shStrTable) + return 0; + + for (uint16 i = 0; i < header->e_shnum; ++i) + { + auto& entry = shTable[i]; + if(entry.sh_type == type && std::string_view{&shStrTable[entry.sh_name]} == name) + { + return i; + } + } + return 0; +} + +void* ELFSymbolTable::SectionPointer(uint16 index) +{ + return SectionPointer(shTable[index]); +} + +void* ELFSymbolTable::SectionPointer(const Elf64_Shdr& section) +{ + return (void*)(mappedExecutable + section.sh_offset); +} + +ELFSymbolTable::ELFSymbolTable() +{ + // create file handle + int fd = open("/proc/self/exe", O_RDONLY); + if (!fd) + return; + + // retrieve file size. + struct stat filestats; + if (fstat(fd, &filestats)) + { + close(fd); + return; + } + mappedExecutableSize = filestats.st_size; + + // attempt to map the file + mappedExecutable = (uint8*)(mmap(nullptr, mappedExecutableSize, PROT_READ, MAP_PRIVATE, fd, 0)); + close(fd); + if (!mappedExecutable) + return; + + // verify signature + header = (Elf64_Ehdr*)(mappedExecutable); + constexpr uint8 signature[] = {0x7f, 0x45, 0x4c, 0x46}; + for (size_t i = 0; i < 4; ++i) + { + if (signature[i] != header->e_ident[i]) + { + return; + } + } + + shTable = (Elf64_Shdr*)(mappedExecutable + header->e_shoff); + + Elf64_Shdr& shStrn = shTable[header->e_shstrndx]; + shStrTable = (char*)(mappedExecutable + shStrn.sh_offset); + + strTable = (char*)SectionPointer(FindSection(SHT_STRTAB, ".strtab")); + + Elf64_Shdr& symTabShdr = shTable[FindSection(SHT_SYMTAB, ".symtab")]; + if (symTabShdr.sh_entsize == 0) + return; + + symTableLen = symTabShdr.sh_size / symTabShdr.sh_entsize; + symTable = (Elf64_Sym*)(SectionPointer(symTabShdr)); +} + +ELFSymbolTable::~ELFSymbolTable() +{ + if (mappedExecutable) + munmap(mappedExecutable, mappedExecutableSize); +} + +std::string_view ELFSymbolTable::OffsetToSymbol(uint64 ptr, uint64& fromStart) const +{ + if(!symTable || !strTable) + { + fromStart = -1; + return {}; + } + + for (auto entry = symTable+1; entry < symTable+symTableLen; ++entry) + { + if (ELF64_ST_TYPE(entry->st_info) != STT_FUNC) + continue; + auto begin = entry->st_value; + auto size = entry->st_size; + if(ptr >= begin && ptr < begin+size) + { + fromStart = ptr-begin; + return &strTable[entry->st_name]; + } + } + fromStart = -1; + return {}; +} diff --git a/src/Common/ExceptionHandler/ELFSymbolTable.h b/src/Common/ExceptionHandler/ELFSymbolTable.h new file mode 100644 index 00000000..89248bbb --- /dev/null +++ b/src/Common/ExceptionHandler/ELFSymbolTable.h @@ -0,0 +1,32 @@ +#pragma once +#include +#include + +class ELFSymbolTable +{ +public: + std::string_view OffsetToSymbol(uint64 ptr, uint64& fromStart) const; + + ELFSymbolTable(); + ~ELFSymbolTable(); +private: + uint8* mappedExecutable = nullptr; + size_t mappedExecutableSize = 0; + + Elf64_Ehdr* header = nullptr; + + Elf64_Shdr* shTable = nullptr; + char* shStrTable = nullptr; + + Elf64_Sym* symTable = nullptr; + uint64 symTableLen = 0; + char* strTable = nullptr; + + uint16 FindSection(int type, const std::string_view& name); + + void* SectionPointer (uint16 index); + void* SectionPointer(const Elf64_Shdr& section); + + // ownership of mapped memory, cannot copy. + ELFSymbolTable(const ELFSymbolTable&) = delete; +}; diff --git a/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp b/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp index 86d83bb3..3a5620c2 100644 --- a/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp +++ b/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp @@ -2,41 +2,60 @@ #include #include #include - #include "config/CemuConfig.h" +#include "util/helpers/StringHelpers.h" +#if BOOST_OS_LINUX +#include "ELFSymbolTable.h" +#endif + +#if BOOST_OS_LINUX void demangleAndPrintBacktrace(char** backtrace, size_t size) { + ELFSymbolTable symTable; for (char** i = backtrace; i < backtrace + size; i++) { - std::string traceLine{*i}; + std::string_view traceLine{*i}; + + // basic check to see if the backtrace line matches expected format size_t parenthesesOpen = traceLine.find_last_of('('); size_t parenthesesClose = traceLine.find_last_of(')'); size_t offsetPlus = traceLine.find_last_of('+'); if (!parenthesesOpen || !parenthesesClose || !offsetPlus || offsetPlus < parenthesesOpen || offsetPlus > parenthesesClose) { - // something unexpected was read. fall back to default string + // fall back to default string std::cerr << traceLine << std::endl; continue; } - std::string symbolName = traceLine.substr(parenthesesOpen+1,offsetPlus-parenthesesOpen-1); - int status = -1; - char* demangled = abi::__cxa_demangle(symbolName.c_str(), nullptr, nullptr, &status); - if (demangled) + // attempt to resolve symbol from regular symbol table if missing from dynamic symbol table + uint64 newOffset = -1; + std::string_view symbolName = traceLine.substr(parenthesesOpen+1, offsetPlus-parenthesesOpen-1); + if (symbolName.empty()) { - std::cerr << traceLine.substr(0, parenthesesOpen+1); - std::cerr << demangled; - std::cerr << traceLine.substr(offsetPlus) << std::endl; - free(demangled); + uint64 symbolOffset = StringHelpers::ToInt64(traceLine.substr(offsetPlus+1,offsetPlus+1-parenthesesClose-1)); + symbolName = symTable.OffsetToSymbol(symbolOffset, newOffset); + } + + std::cerr << traceLine.substr(0, parenthesesOpen+1); + + std::cerr << boost::core::demangle(symbolName.empty() ? "" : symbolName.data()); + + // print relative or existing symbol offset. + std::cerr << '+'; + if (newOffset != -1) + { + std::cerr << std::hex << newOffset; + std::cerr << traceLine.substr(parenthesesClose) << std::endl; } else { - std::cerr << traceLine << std::endl; + std::cerr << traceLine.substr(offsetPlus+1) << std::endl; } } } +#endif // handle signals that would dump core, print stacktrace and then dump depending on config void handlerDumpingSignal(int sig) @@ -61,6 +80,7 @@ void handlerDumpingSignal(int sig) // print out all the frames to stderr fprintf(stderr, "Error: signal %d:\n", sig); +#if BOOST_OS_LINUX char** symbol_trace = backtrace_symbols(array, size); if (symbol_trace) @@ -72,6 +92,9 @@ void handlerDumpingSignal(int sig) { std::cerr << "Failed to read backtrace" << std::endl; } +#else + backtrace_symbols_fd(array, size, STDERR_FILENO); +#endif if (GetConfig().crash_dump == CrashDump::Enabled) { From dd1cb1cccf9ebc46f1b66b0a74d0e1ca86a0b99c Mon Sep 17 00:00:00 2001 From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com> Date: Thu, 20 Oct 2022 13:18:44 +0200 Subject: [PATCH 011/589] Update title manager when clearing MLC path in settings (#319) --- src/gui/CemuApp.cpp | 28 ++++++++++++++++++++-------- src/gui/CemuApp.h | 1 + src/gui/GeneralSettings2.cpp | 17 ++++++++++------- src/util/helpers/helpers.cpp | 6 +++--- 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/gui/CemuApp.cpp b/src/gui/CemuApp.cpp index c7a5adaa..c502e8d2 100644 --- a/src/gui/CemuApp.cpp +++ b/src/gui/CemuApp.cpp @@ -376,6 +376,24 @@ void CemuApp::CreateDefaultFiles(bool first_start) } +bool CemuApp::TrySelectMLCPath(std::wstring path) +{ + if (path.empty()) + path = ActiveSettings::GetDefaultMLCPath().wstring(); + + if (!TestWriteAccess(fs::path{ path })) + return false; + + GetConfig().SetMLCPath(path); + CemuApp::CreateDefaultFiles(); + + // update TitleList and SaveList scanner with new MLC path + CafeTitleList::SetMLCPath(path); + CafeTitleList::Refresh(); + CafeSaveList::SetMLCPath(path); + CafeSaveList::Refresh(); + return true; +} bool CemuApp::SelectMLCPath(wxWindow* parent) { @@ -394,21 +412,15 @@ bool CemuApp::SelectMLCPath(wxWindow* parent) const auto path = path_dialog.GetPath().ToStdWstring(); - if (!TestWriteAccess(fs::path{ path })) + if (!TrySelectMLCPath(path)) { const auto result = wxMessageBox(_("Cemu can't write to the selected mlc path!\nDo you want to select another path?"), _("Error"), wxYES_NO | wxCENTRE | wxICON_ERROR); if (result == wxYES) continue; - + break; } - config.SetMLCPath(path); - // update TitleList and SaveList scanner with new MLC path - CafeTitleList::SetMLCPath(path); - CafeTitleList::Refresh(); - CafeSaveList::SetMLCPath(path); - CafeSaveList::Refresh(); return true; } diff --git a/src/gui/CemuApp.h b/src/gui/CemuApp.h index 32504883..f462ec39 100644 --- a/src/gui/CemuApp.h +++ b/src/gui/CemuApp.h @@ -17,6 +17,7 @@ public: static std::vector GetAvailableLanguages(); static void CreateDefaultFiles(bool first_start = false); + static bool TrySelectMLCPath(std::wstring path); static bool SelectMLCPath(wxWindow* parent = nullptr); static wxString GetConfigPath(); diff --git a/src/gui/GeneralSettings2.cpp b/src/gui/GeneralSettings2.cpp index 776afc2e..810c147e 100644 --- a/src/gui/GeneralSettings2.cpp +++ b/src/gui/GeneralSettings2.cpp @@ -1751,7 +1751,6 @@ void GeneralSettings2::OnMLCPathSelect(wxCommandEvent& event) m_mlc_path->SetValue(ActiveSettings::GetMlcPath().generic_string()); m_reload_gamelist = true; m_mlc_modified = true; - CemuApp::CreateDefaultFiles(); } void GeneralSettings2::OnMLCPathChar(wxKeyEvent& event) @@ -1761,14 +1760,18 @@ void GeneralSettings2::OnMLCPathChar(wxKeyEvent& event) if(event.GetKeyCode() == WXK_DELETE || event.GetKeyCode() == WXK_BACK) { - m_mlc_path->SetValue(wxEmptyString); + std::wstring newPath = L""; + if(!CemuApp::TrySelectMLCPath(newPath)) + { + const auto res = wxMessageBox(_("The default MLC path is inaccessible.\nDo you want to select a different path?"), _("Error"), wxYES_NO | wxCENTRE | wxICON_ERROR); + if (res == wxYES && CemuApp::SelectMLCPath(this)) + newPath = ActiveSettings::GetMlcPath().wstring(); + else + return; + } + m_mlc_path->SetValue(newPath); m_reload_gamelist = true; - - GetConfig().mlc_path = L""; - g_config.Save(); m_mlc_modified = true; - - CemuApp::CreateDefaultFiles(); } } diff --git a/src/util/helpers/helpers.cpp b/src/util/helpers/helpers.cpp index fefe7985..b556db36 100644 --- a/src/util/helpers/helpers.cpp +++ b/src/util/helpers/helpers.cpp @@ -280,15 +280,16 @@ uint32_t GetPhysicalCoreCount() bool TestWriteAccess(const fs::path& p) { + std::error_code ec; // must be path and must exist - if (!fs::exists(p) || !fs::is_directory(p)) + if (!fs::exists(p, ec) || !fs::is_directory(p, ec)) return false; // retry 3 times for (int i = 0; i < 3; ++i) { const auto filename = p / fmt::format("_{}.tmp", GenerateRandomString(8)); - if (fs::exists(filename)) + if (fs::exists(filename, ec)) continue; std::ofstream file(filename); @@ -297,7 +298,6 @@ bool TestWriteAccess(const fs::path& p) file.close(); - std::error_code ec; fs::remove(filename, ec); return true; } From c217b3ee3231d5b7e2eed21896f72e9de05f5ea1 Mon Sep 17 00:00:00 2001 From: MythicalPlayz <57963367+MythicalPlayz@users.noreply.github.com> Date: Fri, 21 Oct 2022 00:17:11 +0200 Subject: [PATCH 012/589] GameList: Use title name based on console language (#388) --- src/Cafe/CafeSystem.cpp | 8 +++++++- src/Cafe/TitleList/TitleInfo.cpp | 10 +++++++++- src/gui/MainWindow.cpp | 2 ++ src/gui/components/wxGameList.cpp | 5 +++++ src/gui/components/wxGameList.h | 1 + 5 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/Cafe/CafeSystem.cpp b/src/Cafe/CafeSystem.cpp index acfd1d2f..68484830 100644 --- a/src/Cafe/CafeSystem.cpp +++ b/src/Cafe/CafeSystem.cpp @@ -705,7 +705,13 @@ namespace CafeSystem { if (sLaunchModeIsStandalone) return "Unknown Game"; - return sGameInfo_ForegroundTitle.GetBase().GetMetaInfo()->GetShortName(GetConfig().console_language); + std::string applicationName; + applicationName = sGameInfo_ForegroundTitle.GetBase().GetMetaInfo()->GetShortName(GetConfig().console_language); + if (applicationName.empty()) //Try to get the English Title + applicationName = sGameInfo_ForegroundTitle.GetBase().GetMetaInfo()->GetShortName(CafeConsoleLanguage::EN); + if (applicationName.empty()) //Unknown Game + applicationName = "Unknown Game"; + return applicationName; } std::string GetForegroundTitleArgStr() diff --git a/src/Cafe/TitleList/TitleInfo.cpp b/src/Cafe/TitleList/TitleInfo.cpp index 10710c43..36814ab8 100644 --- a/src/Cafe/TitleList/TitleInfo.cpp +++ b/src/Cafe/TitleList/TitleInfo.cpp @@ -589,7 +589,15 @@ std::string TitleInfo::GetTitleName() const { cemu_assert_debug(m_isValid); if (m_parsedMetaXml) - return m_parsedMetaXml->GetShortName(CafeConsoleLanguage::EN); + { + std::string titleNameCfgLanguage; + titleNameCfgLanguage = m_parsedMetaXml->GetShortName(GetConfig().console_language); + if (titleNameCfgLanguage.empty()) //Get English Title + titleNameCfgLanguage = m_parsedMetaXml->GetShortName(CafeConsoleLanguage::EN); + if (titleNameCfgLanguage.empty()) //Unknown Title + titleNameCfgLanguage = "Unknown Title"; + return titleNameCfgLanguage; + } if (m_cachedInfo) return m_cachedInfo->titleName; cemu_assert_suspicious(); diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index fb18a7de..e8d1c920 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -931,6 +931,8 @@ void MainWindow::OnConsoleLanguage(wxCommandEvent& event) default: cemu_assert_debug(false); } + m_game_list->DeleteCachedStrings(); + m_game_list->ReloadGameEntries(false); g_config.Save(); } diff --git a/src/gui/components/wxGameList.cpp b/src/gui/components/wxGameList.cpp index 904fd5b7..50a6254a 100644 --- a/src/gui/components/wxGameList.cpp +++ b/src/gui/components/wxGameList.cpp @@ -1139,3 +1139,8 @@ bool wxGameList::QueryIconForTitle(TitleId titleId, int& icon, int& iconSmall) m_icon_cache_mtx.unlock(); return true; } + +void wxGameList::DeleteCachedStrings() +{ + m_name_cache.clear(); +} \ No newline at end of file diff --git a/src/gui/components/wxGameList.h b/src/gui/components/wxGameList.h index 2cf9f6b7..f8efd5d2 100644 --- a/src/gui/components/wxGameList.h +++ b/src/gui/components/wxGameList.h @@ -50,6 +50,7 @@ public: bool IsVisible(long item) const; // only available in wxwidgets 3.1.3 void ReloadGameEntries(bool cached = false); + void DeleteCachedStrings(); long FindListItemByTitleId(uint64 title_id) const; void OnClose(wxCloseEvent& event); From ffa213c794d6c11bea370ce445f36d2ede8acf6c Mon Sep 17 00:00:00 2001 From: Squall Leonhart Date: Fri, 21 Oct 2022 21:39:26 +1100 Subject: [PATCH 013/589] Generalised game profile cleanup and corrections (#389) --- bin/gameProfiles/default/0005000010101a00.ini | 8 +------- bin/gameProfiles/default/0005000010101b00.ini | 8 +------- bin/gameProfiles/default/0005000010104d00.ini | 1 - bin/gameProfiles/default/0005000010106100.ini | 3 --- bin/gameProfiles/default/000500001010EB00.ini | 3 --- bin/gameProfiles/default/000500001010F900.ini | 8 +------- bin/gameProfiles/default/000500001010ac00.ini | 8 +------- bin/gameProfiles/default/000500001010b100.ini | 5 +---- bin/gameProfiles/default/000500001010b200.ini | 8 +------- bin/gameProfiles/default/000500001010dc00.ini | 5 +---- bin/gameProfiles/default/000500001010dd00.ini | 5 +---- bin/gameProfiles/default/000500001010e600.ini | 5 +---- bin/gameProfiles/default/000500001010e700.ini | 8 +------- bin/gameProfiles/default/000500001010ec00.ini | 3 --- bin/gameProfiles/default/000500001010ed00.ini | 3 --- bin/gameProfiles/default/000500001010ef00.ini | 5 +---- bin/gameProfiles/default/000500001010f100.ini | 8 +------- bin/gameProfiles/default/000500001010f200.ini | 8 +------- bin/gameProfiles/default/000500001010f500.ini | 5 +---- bin/gameProfiles/default/000500001011000.ini | 8 +------- bin/gameProfiles/default/0005000010110100.ini | 5 +---- bin/gameProfiles/default/0005000010110600.ini | 5 +---- bin/gameProfiles/default/0005000010110700.ini | 5 +---- bin/gameProfiles/default/0005000010110E00.ini | 1 - bin/gameProfiles/default/0005000010111400.ini | 5 +---- bin/gameProfiles/default/0005000010111600.ini | 8 +------- bin/gameProfiles/default/0005000010112000.ini | 5 +---- bin/gameProfiles/default/0005000010112300.ini | 5 +---- bin/gameProfiles/default/0005000010113000.ini | 5 +---- bin/gameProfiles/default/0005000010113300.ini | 5 +---- bin/gameProfiles/default/0005000010113d00.ini | 5 +---- bin/gameProfiles/default/0005000010115d00.ini | 5 +---- bin/gameProfiles/default/0005000010116100.ini | 1 - bin/gameProfiles/default/0005000010117200.ini | 1 - bin/gameProfiles/default/0005000010118300.ini | 1 - bin/gameProfiles/default/000500001011a600.ini | 8 +------- bin/gameProfiles/default/000500001011af00.ini | 5 +---- bin/gameProfiles/default/000500001011b200.ini | 5 +---- bin/gameProfiles/default/0005000010128600.ini | 3 +-- bin/gameProfiles/default/0005000010129000.ini | 1 - bin/gameProfiles/default/0005000010129200.ini | 1 - bin/gameProfiles/default/000500001012BC00.ini | 4 ---- bin/gameProfiles/default/000500001012BD00.ini | 4 ---- bin/gameProfiles/default/000500001012F000.ini | 3 --- bin/gameProfiles/default/000500001012b200.ini | 1 - bin/gameProfiles/default/000500001012ba00.ini | 1 - bin/gameProfiles/default/000500001012be00.ini | 3 --- bin/gameProfiles/default/000500001012c500.ini | 5 +---- bin/gameProfiles/default/000500001012da00.ini | 8 +------- bin/gameProfiles/default/0005000010131F00.ini | 5 +---- bin/gameProfiles/default/0005000010132c00.ini | 5 +---- bin/gameProfiles/default/0005000010132d00.ini | 5 +---- bin/gameProfiles/default/0005000010133b00.ini | 5 +---- bin/gameProfiles/default/0005000010134e00.ini | 5 +---- bin/gameProfiles/default/0005000010135500.ini | 8 +------- bin/gameProfiles/default/0005000010135e00.ini | 6 +----- bin/gameProfiles/default/0005000010136300.ini | 5 +---- bin/gameProfiles/default/0005000010136c00.ini | 1 - bin/gameProfiles/default/0005000010137F00.ini | 5 +---- bin/gameProfiles/default/0005000010137c00.ini | 1 - bin/gameProfiles/default/0005000010138300.ini | 5 +---- bin/gameProfiles/default/0005000010138a00.ini | 5 +---- bin/gameProfiles/default/0005000010138f00.ini | 1 - bin/gameProfiles/default/0005000010140000.ini | 5 +---- bin/gameProfiles/default/0005000010143200.ini | 1 + bin/gameProfiles/default/0005000010143500.ini | 7 +------ bin/gameProfiles/default/0005000010143600.ini | 7 +------ bin/gameProfiles/default/0005000010144800.ini | 5 +---- bin/gameProfiles/default/0005000010144f00.ini | 1 - bin/gameProfiles/default/0005000010145000.ini | 1 - bin/gameProfiles/default/0005000010145c00.ini | 5 +---- bin/gameProfiles/default/0005000010145d00.ini | 5 +---- bin/gameProfiles/default/0005000010147e00.ini | 5 +---- bin/gameProfiles/default/000500001014c100.ini | 5 +---- bin/gameProfiles/default/000500001014c600.ini | 5 +---- bin/gameProfiles/default/000500001014cb00.ini | 5 +---- bin/gameProfiles/default/000500001014d900.ini | 5 +---- bin/gameProfiles/default/0005000010154600.ini | 1 - bin/gameProfiles/default/000500001015b200.ini | 5 +---- bin/gameProfiles/default/0005000010161a00.ini | 5 +---- bin/gameProfiles/default/0005000010162200.ini | 5 +---- bin/gameProfiles/default/0005000010162a00.ini | 5 +---- bin/gameProfiles/default/0005000010162b00.ini | 7 +------ bin/gameProfiles/default/000500001016a200.ini | 5 +---- bin/gameProfiles/default/000500001016ab00.ini | 5 +---- bin/gameProfiles/default/000500001016b200.ini | 3 --- bin/gameProfiles/default/000500001016d400.ini | 5 +---- bin/gameProfiles/default/000500001016d800.ini | 5 +---- bin/gameProfiles/default/000500001016da00.ini | 3 --- bin/gameProfiles/default/000500001016e000.ini | 5 +---- bin/gameProfiles/default/000500001016e800.ini | 3 --- bin/gameProfiles/default/000500001016ea00.ini | 5 +---- bin/gameProfiles/default/000500001016fc00.ini | 3 +-- bin/gameProfiles/default/0005000010170100.ini | 5 +---- bin/gameProfiles/default/0005000010172900.ini | 3 +-- bin/gameProfiles/default/0005000010173400.ini | 5 +---- bin/gameProfiles/default/0005000010176300.ini | 3 +-- bin/gameProfiles/default/0005000010176900.ini | 7 +------ bin/gameProfiles/default/0005000010176a00.ini | 7 +------ bin/gameProfiles/default/0005000010177000.ini | 5 +---- bin/gameProfiles/default/0005000010177500.ini | 3 --- bin/gameProfiles/default/0005000010177600.ini | 1 - bin/gameProfiles/default/0005000010177700.ini | 1 - bin/gameProfiles/default/000500001017da00.ini | 5 +---- bin/gameProfiles/default/000500001017e400.ini | 5 +---- bin/gameProfiles/default/0005000010180500.ini | 3 --- bin/gameProfiles/default/0005000010180600.ini | 3 --- bin/gameProfiles/default/0005000010180700.ini | 3 --- bin/gameProfiles/default/0005000010183000.ini | 8 +------- bin/gameProfiles/default/0005000010184900.ini | 5 +---- bin/gameProfiles/default/0005000010184E00.ini | 7 +------ bin/gameProfiles/default/0005000010184d00.ini | 7 +------ bin/gameProfiles/default/0005000010185400.ini | 7 +------ bin/gameProfiles/default/0005000010189f00.ini | 3 --- bin/gameProfiles/default/000500001018ab00.ini | 5 +---- bin/gameProfiles/default/000500001018d800.ini | 5 +---- bin/gameProfiles/default/000500001018d900.ini | 3 --- bin/gameProfiles/default/000500001018f100.ini | 5 +---- bin/gameProfiles/default/000500001018f400.ini | 5 +---- bin/gameProfiles/default/000500001018fd00.ini | 5 +---- bin/gameProfiles/default/0005000010190300.ini | 5 +---- bin/gameProfiles/default/0005000010193f00.ini | 5 +---- bin/gameProfiles/default/0005000010195e00.ini | 5 +---- bin/gameProfiles/default/0005000010197300.ini | 5 +---- bin/gameProfiles/default/0005000010197800.ini | 5 +---- bin/gameProfiles/default/0005000010199e00.ini | 5 +---- bin/gameProfiles/default/000500001019ab00.ini | 5 +---- bin/gameProfiles/default/000500001019b000.ini | 5 +---- bin/gameProfiles/default/000500001019b200.ini | 5 +---- bin/gameProfiles/default/000500001019ca00.ini | 5 +---- bin/gameProfiles/default/000500001019e500.ini | 7 +------ bin/gameProfiles/default/000500001019e600.ini | 7 +------ bin/gameProfiles/default/000500001019ea00.ini | 5 +---- bin/gameProfiles/default/000500001019ee00.ini | 5 +---- bin/gameProfiles/default/00050000101C9300.ini | 1 - bin/gameProfiles/default/00050000101E4100.ini | 3 --- bin/gameProfiles/default/00050000101a1200.ini | 6 +----- bin/gameProfiles/default/00050000101a1800.ini | 5 +---- bin/gameProfiles/default/00050000101a3b00.ini | 5 +---- bin/gameProfiles/default/00050000101a4300.ini | 5 +---- bin/gameProfiles/default/00050000101a4800.ini | 3 --- bin/gameProfiles/default/00050000101a4900.ini | 5 +---- bin/gameProfiles/default/00050000101a7f00.ini | 5 +---- bin/gameProfiles/default/00050000101a9c00.ini | 5 +---- bin/gameProfiles/default/00050000101a9e00.ini | 5 +---- bin/gameProfiles/default/00050000101acc00.ini | 5 +---- bin/gameProfiles/default/00050000101b0100.ini | 5 +---- bin/gameProfiles/default/00050000101b4e00.ini | 5 +---- bin/gameProfiles/default/00050000101b9900.ini | 3 --- bin/gameProfiles/default/00050000101bc300.ini | 5 +---- bin/gameProfiles/default/00050000101c3100.ini | 5 +---- bin/gameProfiles/default/00050000101c4200.ini | 5 +---- bin/gameProfiles/default/00050000101c4300.ini | 3 --- bin/gameProfiles/default/00050000101c4c00.ini | 1 - bin/gameProfiles/default/00050000101c4d00.ini | 1 - bin/gameProfiles/default/00050000101c6c00.ini | 5 +---- bin/gameProfiles/default/00050000101c7600.ini | 5 +---- bin/gameProfiles/default/00050000101c7b00.ini | 5 +---- bin/gameProfiles/default/00050000101c7d00.ini | 5 +---- bin/gameProfiles/default/00050000101c9400.ini | 1 - bin/gameProfiles/default/00050000101c9500.ini | 1 - bin/gameProfiles/default/00050000101c9a00.ini | 3 --- bin/gameProfiles/default/00050000101cc900.ini | 5 +---- bin/gameProfiles/default/00050000101ccf00.ini | 5 +---- bin/gameProfiles/default/00050000101ce000.ini | 5 +---- bin/gameProfiles/default/00050000101ce800.ini | 5 +---- bin/gameProfiles/default/00050000101d2100.ini | 3 +-- bin/gameProfiles/default/00050000101d4500.ini | 5 +---- bin/gameProfiles/default/00050000101d4d00.ini | 5 +---- bin/gameProfiles/default/00050000101d5000.ini | 5 +---- bin/gameProfiles/default/00050000101d5500.ini | 5 +---- bin/gameProfiles/default/00050000101d6000.ini | 3 --- bin/gameProfiles/default/00050000101d6d00.ini | 8 +------- bin/gameProfiles/default/00050000101d7500.ini | 3 --- bin/gameProfiles/default/00050000101d8900.ini | 5 +---- bin/gameProfiles/default/00050000101d8d00.ini | 5 +---- bin/gameProfiles/default/00050000101d9600.ini | 5 +---- bin/gameProfiles/default/00050000101d9d00.ini | 3 --- bin/gameProfiles/default/00050000101dac00.ini | 5 +---- bin/gameProfiles/default/00050000101daf00.ini | 5 +---- bin/gameProfiles/default/00050000101db000.ini | 5 +---- bin/gameProfiles/default/00050000101dbb00.ini | 5 +---- bin/gameProfiles/default/00050000101dbc00.ini | 5 +---- bin/gameProfiles/default/00050000101dbe00.ini | 5 +---- bin/gameProfiles/default/00050000101dbf00.ini | 5 +---- bin/gameProfiles/default/00050000101dc000.ini | 5 +---- bin/gameProfiles/default/00050000101dc200.ini | 5 +---- bin/gameProfiles/default/00050000101dd000.ini | 5 +---- bin/gameProfiles/default/00050000101dd600.ini | 5 +---- bin/gameProfiles/default/00050000101dd700.ini | 8 +------- bin/gameProfiles/default/00050000101ddf00.ini | 5 +---- bin/gameProfiles/default/00050000101e0100.ini | 7 +------ bin/gameProfiles/default/00050000101e1800.ini | 5 +---- bin/gameProfiles/default/00050000101e1a00.ini | 5 +---- bin/gameProfiles/default/00050000101e1b00.ini | 3 --- bin/gameProfiles/default/00050000101e3800.ini | 8 +------- bin/gameProfiles/default/00050000101e4200.ini | 3 --- bin/gameProfiles/default/00050000101e5300.ini | 3 --- bin/gameProfiles/default/00050000101e5400.ini | 3 --- bin/gameProfiles/default/00050000101e5e00.ini | 5 +---- bin/gameProfiles/default/00050000101e7300.ini | 5 +---- bin/gameProfiles/default/00050000101e7400.ini | 5 +---- bin/gameProfiles/default/00050000101e9300.ini | 5 +---- bin/gameProfiles/default/00050000101e9400.ini | 5 +---- bin/gameProfiles/default/00050000101eb300.ini | 5 +---- bin/gameProfiles/default/00050000101ec700.ini | 5 +---- bin/gameProfiles/default/00050000101ecf00.ini | 5 +---- bin/gameProfiles/default/00050000101f1300.ini | 5 +---- bin/gameProfiles/default/00050000101f2800.ini | 3 --- bin/gameProfiles/default/00050000101f4a00.ini | 5 +---- bin/gameProfiles/default/00050000101f5700.ini | 5 +---- bin/gameProfiles/default/00050000101f6f00.ini | 5 +---- bin/gameProfiles/default/00050000101f7600.ini | 8 +------- bin/gameProfiles/default/00050000101f9700.ini | 5 +---- bin/gameProfiles/default/00050000101fa600.ini | 5 +---- bin/gameProfiles/default/00050000101fd100.ini | 5 +---- bin/gameProfiles/default/00050000101ff200.ini | 5 +---- bin/gameProfiles/default/00050000101ffc00.ini | 1 - bin/gameProfiles/default/00050000101ffe00.ini | 5 +---- bin/gameProfiles/default/0005000010200300.ini | 5 +---- bin/gameProfiles/default/0005000010200b00.ini | 5 +---- bin/gameProfiles/default/0005000010204a00.ini | 5 +---- bin/gameProfiles/default/0005000010207300.ini | 5 +---- bin/gameProfiles/default/0005000010207500.ini | 5 +---- bin/gameProfiles/default/000500001020a200.ini | 6 +----- bin/gameProfiles/default/000500001020b600.ini | 1 - bin/gameProfiles/default/0005000010211b00.ini | 5 +---- bin/gameProfiles/default/0005000C1012BC00.ini | 4 ---- bin/gameProfiles/default/0005000C1012BD00.ini | 4 ---- bin/gameProfiles/default/0005000C1012BE00.ini | 4 ---- bin/gameProfiles/default/0005000e1019c800.ini | 5 +---- 231 files changed, 174 insertions(+), 889 deletions(-) create mode 100644 bin/gameProfiles/default/0005000010143200.ini diff --git a/bin/gameProfiles/default/0005000010101a00.ini b/bin/gameProfiles/default/0005000010101a00.ini index dc63ccb5..1123343a 100644 --- a/bin/gameProfiles/default/0005000010101a00.ini +++ b/bin/gameProfiles/default/0005000010101a00.ini @@ -1,7 +1 @@ -# LEGO City Undercover (USA) - -[General] -loadSharedLibraries = false - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# LEGO City Undercover (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010101b00.ini b/bin/gameProfiles/default/0005000010101b00.ini index 21aded1d..f3749d47 100644 --- a/bin/gameProfiles/default/0005000010101b00.ini +++ b/bin/gameProfiles/default/0005000010101b00.ini @@ -1,7 +1 @@ -# LEGO City Undercover (EUR) - -[General] -loadSharedLibraries = false - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# LEGO City Undercover (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010104d00.ini b/bin/gameProfiles/default/0005000010104d00.ini index 50a9fa48..dc8bebaf 100644 --- a/bin/gameProfiles/default/0005000010104d00.ini +++ b/bin/gameProfiles/default/0005000010104d00.ini @@ -1,5 +1,4 @@ # Monster Hunter 3(tri-)GHD Ver. (JPN) [Graphics] -GPUBufferCacheAccuracy = 1 streamoutBufferCacheSize = 48 \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010106100.ini b/bin/gameProfiles/default/0005000010106100.ini index 77e7c399..9aa38072 100644 --- a/bin/gameProfiles/default/0005000010106100.ini +++ b/bin/gameProfiles/default/0005000010106100.ini @@ -1,7 +1,4 @@ # Super Mario 3D World (JPN) -[CPU] - [Graphics] accurateShaderMul = false -GPUBufferCacheAccuracy = 2 \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001010EB00.ini b/bin/gameProfiles/default/000500001010EB00.ini index e4b30b16..281d21db 100644 --- a/bin/gameProfiles/default/000500001010EB00.ini +++ b/bin/gameProfiles/default/000500001010EB00.ini @@ -2,6 +2,3 @@ [CPU] cpuMode = Singlecore-Recompiler - -[Graphics] -GPUBufferCacheAccuracy = 2 \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001010F900.ini b/bin/gameProfiles/default/000500001010F900.ini index 4772db75..e22770bf 100644 --- a/bin/gameProfiles/default/000500001010F900.ini +++ b/bin/gameProfiles/default/000500001010F900.ini @@ -1,7 +1 @@ -# Scribblenauts Unlimited (EUR) - -[General] -loadSharedLibraries = true - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Scribblenauts Unlimited (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001010ac00.ini b/bin/gameProfiles/default/000500001010ac00.ini index 7df76e2f..9852538c 100644 --- a/bin/gameProfiles/default/000500001010ac00.ini +++ b/bin/gameProfiles/default/000500001010ac00.ini @@ -1,7 +1 @@ -# Ben 10 Omniverse (USA) - -[General] -loadSharedLibraries = false - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Ben 10 Omniverse (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001010b100.ini b/bin/gameProfiles/default/000500001010b100.ini index e2215587..0741b39f 100644 --- a/bin/gameProfiles/default/000500001010b100.ini +++ b/bin/gameProfiles/default/000500001010b100.ini @@ -1,4 +1 @@ -# Rayman Legends (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Rayman Legends (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001010b200.ini b/bin/gameProfiles/default/000500001010b200.ini index d47b4060..22d51c39 100644 --- a/bin/gameProfiles/default/000500001010b200.ini +++ b/bin/gameProfiles/default/000500001010b200.ini @@ -1,7 +1 @@ -# Scribblenauts Unlimited (US) - -[General] -loadSharedLibraries = true - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Scribblenauts Unlimited (US) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001010dc00.ini b/bin/gameProfiles/default/000500001010dc00.ini index 11d0fd68..ffed75ea 100644 --- a/bin/gameProfiles/default/000500001010dc00.ini +++ b/bin/gameProfiles/default/000500001010dc00.ini @@ -1,4 +1 @@ -# Mass Effect 3 Special Edition (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Mass Effect 3 Special Edition (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001010dd00.ini b/bin/gameProfiles/default/000500001010dd00.ini index 5a0620da..2e74d7e0 100644 --- a/bin/gameProfiles/default/000500001010dd00.ini +++ b/bin/gameProfiles/default/000500001010dd00.ini @@ -1,4 +1 @@ -# ZombiU (US) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# ZombiU (US) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001010e600.ini b/bin/gameProfiles/default/000500001010e600.ini index dc351608..01dc0e7a 100644 --- a/bin/gameProfiles/default/000500001010e600.ini +++ b/bin/gameProfiles/default/000500001010e600.ini @@ -1,4 +1 @@ -# 007 Legends (US) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# 007 Legends (US) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001010e700.ini b/bin/gameProfiles/default/000500001010e700.ini index ea118074..a926c9d4 100644 --- a/bin/gameProfiles/default/000500001010e700.ini +++ b/bin/gameProfiles/default/000500001010e700.ini @@ -1,7 +1 @@ -# Cabela's Dangerous Hunts 2013 (USA) - -[General] -loadSharedLibraries = false - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Cabela's Dangerous Hunts 2013 (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001010ec00.ini b/bin/gameProfiles/default/000500001010ec00.ini index babaf249..697aace3 100644 --- a/bin/gameProfiles/default/000500001010ec00.ini +++ b/bin/gameProfiles/default/000500001010ec00.ini @@ -2,6 +2,3 @@ [CPU] cpuMode = Singlecore-Recompiler - -[Graphics] -GPUBufferCacheAccuracy = 2 \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001010ed00.ini b/bin/gameProfiles/default/000500001010ed00.ini index 7935ea37..23e1dffc 100644 --- a/bin/gameProfiles/default/000500001010ed00.ini +++ b/bin/gameProfiles/default/000500001010ed00.ini @@ -2,6 +2,3 @@ [CPU] cpuMode = Singlecore-Recompiler - -[Graphics] -GPUBufferCacheAccuracy = 2 \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001010ef00.ini b/bin/gameProfiles/default/000500001010ef00.ini index 005ba84b..dbadd2b1 100644 --- a/bin/gameProfiles/default/000500001010ef00.ini +++ b/bin/gameProfiles/default/000500001010ef00.ini @@ -1,4 +1 @@ -# ZombiU (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# ZombiU (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001010f100.ini b/bin/gameProfiles/default/000500001010f100.ini index c557498c..025e3e70 100644 --- a/bin/gameProfiles/default/000500001010f100.ini +++ b/bin/gameProfiles/default/000500001010f100.ini @@ -1,7 +1 @@ -# Rise of the Guardians: The Video Game (EUR) - -[General] -loadSharedLibraries = false - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Rise of the Guardians: The Video Game (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001010f200.ini b/bin/gameProfiles/default/000500001010f200.ini index 055fda32..507b374b 100644 --- a/bin/gameProfiles/default/000500001010f200.ini +++ b/bin/gameProfiles/default/000500001010f200.ini @@ -1,7 +1 @@ -# Rise of the Guardians: The Video Game (USA) - -[General] -loadSharedLibraries = false - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Rise of the Guardians: The Video Game (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001010f500.ini b/bin/gameProfiles/default/000500001010f500.ini index e1a86417..e598f517 100644 --- a/bin/gameProfiles/default/000500001010f500.ini +++ b/bin/gameProfiles/default/000500001010f500.ini @@ -1,4 +1 @@ -# Mass Effect 3 Special Edition (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Mass Effect 3 Special Edition (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001011000.ini b/bin/gameProfiles/default/000500001011000.ini index 85ebf4c6..8c34cbab 100644 --- a/bin/gameProfiles/default/000500001011000.ini +++ b/bin/gameProfiles/default/000500001011000.ini @@ -1,7 +1 @@ -# Ben 10 Omniverse (EUR) - -[General] -loadSharedLibraries = false - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Ben 10 Omniverse (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010110100.ini b/bin/gameProfiles/default/0005000010110100.ini index 69b988cf..d46267b0 100644 --- a/bin/gameProfiles/default/0005000010110100.ini +++ b/bin/gameProfiles/default/0005000010110100.ini @@ -1,4 +1 @@ -# Nano Assault Neo (USA) - -[Graphics] -GPUBufferCacheAccuracy = 2 \ No newline at end of file +# Nano Assault Neo (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010110600.ini b/bin/gameProfiles/default/0005000010110600.ini index fb19b607..bc0a0552 100644 --- a/bin/gameProfiles/default/0005000010110600.ini +++ b/bin/gameProfiles/default/0005000010110600.ini @@ -1,4 +1 @@ -# Nano Assault Neo (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 2 \ No newline at end of file +# Nano Assault Neo (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010110700.ini b/bin/gameProfiles/default/0005000010110700.ini index e2d361c4..4e88d406 100644 --- a/bin/gameProfiles/default/0005000010110700.ini +++ b/bin/gameProfiles/default/0005000010110700.ini @@ -1,4 +1 @@ -# 007 Legends (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# 007 Legends (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010110E00.ini b/bin/gameProfiles/default/0005000010110E00.ini index 3064350f..6c56910f 100644 --- a/bin/gameProfiles/default/0005000010110E00.ini +++ b/bin/gameProfiles/default/0005000010110E00.ini @@ -5,4 +5,3 @@ cpuMode = Singlecore-Recompiler [Graphics] streamoutBufferCacheSize = 48 -GPUBufferCacheAccuracy = 2 \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010111400.ini b/bin/gameProfiles/default/0005000010111400.ini index 7fee0ed1..baa50914 100644 --- a/bin/gameProfiles/default/0005000010111400.ini +++ b/bin/gameProfiles/default/0005000010111400.ini @@ -1,4 +1 @@ -# Rayman Legends (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Rayman Legends (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010111600.ini b/bin/gameProfiles/default/0005000010111600.ini index 6b433160..f1c13f22 100644 --- a/bin/gameProfiles/default/0005000010111600.ini +++ b/bin/gameProfiles/default/0005000010111600.ini @@ -1,7 +1 @@ -# Fast And Furious Showdown (USA) - -[General] -loadSharedLibraries = false - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Fast And Furious Showdown (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010112000.ini b/bin/gameProfiles/default/0005000010112000.ini index 853fc36b..3c7710d9 100644 --- a/bin/gameProfiles/default/0005000010112000.ini +++ b/bin/gameProfiles/default/0005000010112000.ini @@ -1,4 +1 @@ -# The Croods: Prehistoric Party! (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# The Croods: Prehistoric Party! (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010112300.ini b/bin/gameProfiles/default/0005000010112300.ini index 5fe50f24..37d8050f 100644 --- a/bin/gameProfiles/default/0005000010112300.ini +++ b/bin/gameProfiles/default/0005000010112300.ini @@ -1,4 +1 @@ -# ZombiU (JPN) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# ZombiU (JPN) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010113000.ini b/bin/gameProfiles/default/0005000010113000.ini index 30330b89..6c023330 100644 --- a/bin/gameProfiles/default/0005000010113000.ini +++ b/bin/gameProfiles/default/0005000010113000.ini @@ -1,4 +1 @@ -# Mass Effect 3 Special Edition (JPN) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Mass Effect 3 Special Edition (JPN) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010113300.ini b/bin/gameProfiles/default/0005000010113300.ini index af55851d..5118d05f 100644 --- a/bin/gameProfiles/default/0005000010113300.ini +++ b/bin/gameProfiles/default/0005000010113300.ini @@ -1,4 +1 @@ -# The Smurfs 2 (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# The Smurfs 2 (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010113d00.ini b/bin/gameProfiles/default/0005000010113d00.ini index 51369705..afb42bf8 100644 --- a/bin/gameProfiles/default/0005000010113d00.ini +++ b/bin/gameProfiles/default/0005000010113d00.ini @@ -1,4 +1 @@ -# Rapala Pro Bass Fishing (US) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Rapala Pro Bass Fishing (US) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010115d00.ini b/bin/gameProfiles/default/0005000010115d00.ini index 5a00554b..84bb9fad 100644 --- a/bin/gameProfiles/default/0005000010115d00.ini +++ b/bin/gameProfiles/default/0005000010115d00.ini @@ -1,4 +1 @@ -# The Smurfs 2 (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# The Smurfs 2 (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010116100.ini b/bin/gameProfiles/default/0005000010116100.ini index 8f01e5fa..465d3dc3 100644 --- a/bin/gameProfiles/default/0005000010116100.ini +++ b/bin/gameProfiles/default/0005000010116100.ini @@ -5,4 +5,3 @@ cpuMode = Singlecore-Recompiler [Graphics] accurateShaderMul = false -GPUBufferCacheAccuracy = 2 \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010117200.ini b/bin/gameProfiles/default/0005000010117200.ini index e802c38e..4000f79f 100644 --- a/bin/gameProfiles/default/0005000010117200.ini +++ b/bin/gameProfiles/default/0005000010117200.ini @@ -1,5 +1,4 @@ # Monster Hunter 3 Ultimate (EUR) [Graphics] -GPUBufferCacheAccuracy = 1 streamoutBufferCacheSize = 48 \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010118300.ini b/bin/gameProfiles/default/0005000010118300.ini index 4ba8d937..e69a6b95 100644 --- a/bin/gameProfiles/default/0005000010118300.ini +++ b/bin/gameProfiles/default/0005000010118300.ini @@ -1,5 +1,4 @@ # Monster Hunter 3 Ultimate (USA) [Graphics] -GPUBufferCacheAccuracy = 1 streamoutBufferCacheSize = 48 \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001011a600.ini b/bin/gameProfiles/default/000500001011a600.ini index 7c673d05..454aaf08 100644 --- a/bin/gameProfiles/default/000500001011a600.ini +++ b/bin/gameProfiles/default/000500001011a600.ini @@ -1,7 +1 @@ -# Cabela's Dangerous Hunts 2013 (EUR) - -[General] -loadSharedLibraries = false - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Cabela's Dangerous Hunts 2013 (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001011af00.ini b/bin/gameProfiles/default/000500001011af00.ini index c7bc4826..73c8f567 100644 --- a/bin/gameProfiles/default/000500001011af00.ini +++ b/bin/gameProfiles/default/000500001011af00.ini @@ -1,4 +1 @@ -# BIT.TRIP Presents... Runner2: Future Legend of Rhythm Alien (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# BIT.TRIP Presents... Runner2: Future Legend of Rhythm Alien (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001011b200.ini b/bin/gameProfiles/default/000500001011b200.ini index 64edf0af..4a576434 100644 --- a/bin/gameProfiles/default/000500001011b200.ini +++ b/bin/gameProfiles/default/000500001011b200.ini @@ -1,7 +1,4 @@ # Little Inferno (US) -[CPU] -extendedTextureReadback = true - [Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +extendedTextureReadback = true \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010128600.ini b/bin/gameProfiles/default/0005000010128600.ini index 467f0014..cd6c1b18 100644 --- a/bin/gameProfiles/default/0005000010128600.ini +++ b/bin/gameProfiles/default/0005000010128600.ini @@ -1,5 +1,4 @@ # Little Inferno (EUR) -[CPU] +[Graphics] extendedTextureReadback = true -GPUBufferCacheAccuracy = 0 \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010129000.ini b/bin/gameProfiles/default/0005000010129000.ini index e1a9d9c5..93403c3c 100644 --- a/bin/gameProfiles/default/0005000010129000.ini +++ b/bin/gameProfiles/default/0005000010129000.ini @@ -4,5 +4,4 @@ cpuMode = Singlecore-Recompiler [Graphics] -GPUBufferCacheAccuracy = 0 streamoutBufferCacheSize = 48 \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010129200.ini b/bin/gameProfiles/default/0005000010129200.ini index 33c2f21a..8705ce00 100644 --- a/bin/gameProfiles/default/0005000010129200.ini +++ b/bin/gameProfiles/default/0005000010129200.ini @@ -4,5 +4,4 @@ cpuMode = Singlecore-Recompiler [Graphics] -GPUBufferCacheAccuracy = 0 streamoutBufferCacheSize = 48 \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001012BC00.ini b/bin/gameProfiles/default/000500001012BC00.ini index c7adb846..0b4f6b6d 100644 --- a/bin/gameProfiles/default/000500001012BC00.ini +++ b/bin/gameProfiles/default/000500001012BC00.ini @@ -1,8 +1,4 @@ # Pikmin 3 (JPN) - - [Graphics] - extendedTextureReadback = true -GPUBufferCacheAccuracy = 2 \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001012BD00.ini b/bin/gameProfiles/default/000500001012BD00.ini index 8ab10175..cd27ff77 100644 --- a/bin/gameProfiles/default/000500001012BD00.ini +++ b/bin/gameProfiles/default/000500001012BD00.ini @@ -1,8 +1,4 @@ # Pikmin 3 (USA) - - [Graphics] - extendedTextureReadback = true -GPUBufferCacheAccuracy = 2 \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001012F000.ini b/bin/gameProfiles/default/000500001012F000.ini index af1229e6..6b1a3f95 100644 --- a/bin/gameProfiles/default/000500001012F000.ini +++ b/bin/gameProfiles/default/000500001012F000.ini @@ -2,6 +2,3 @@ [CPU] cpuMode = Singlecore-Recompiler - -[Graphics] -GPUBufferCacheAccuracy = 1 \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001012b200.ini b/bin/gameProfiles/default/000500001012b200.ini index b00c1a04..9f3733ff 100644 --- a/bin/gameProfiles/default/000500001012b200.ini +++ b/bin/gameProfiles/default/000500001012b200.ini @@ -4,6 +4,5 @@ loadSharedLibraries = false [Graphics] -GPUBufferCacheAccuracy = 0 extendedTextureReadback = true streamoutBufferCacheSize = 48 \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001012ba00.ini b/bin/gameProfiles/default/000500001012ba00.ini index 7e94a7fd..efab660e 100644 --- a/bin/gameProfiles/default/000500001012ba00.ini +++ b/bin/gameProfiles/default/000500001012ba00.ini @@ -4,6 +4,5 @@ loadSharedLibraries = false [Graphics] -GPUBufferCacheAccuracy = 0 extendedTextureReadback = true streamoutBufferCacheSize = 48 \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001012be00.ini b/bin/gameProfiles/default/000500001012be00.ini index 2987dd1e..64a38b0d 100644 --- a/bin/gameProfiles/default/000500001012be00.ini +++ b/bin/gameProfiles/default/000500001012be00.ini @@ -1,7 +1,4 @@ # Pikmin 3 (EU) - - [Graphics] - extendedTextureReadback = true \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001012c500.ini b/bin/gameProfiles/default/000500001012c500.ini index 9badd49e..e4cc6690 100644 --- a/bin/gameProfiles/default/000500001012c500.ini +++ b/bin/gameProfiles/default/000500001012c500.ini @@ -1,4 +1 @@ -# The Croods: Prehistoric Party! (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# The Croods: Prehistoric Party! (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001012da00.ini b/bin/gameProfiles/default/000500001012da00.ini index 4f478ace..8812e297 100644 --- a/bin/gameProfiles/default/000500001012da00.ini +++ b/bin/gameProfiles/default/000500001012da00.ini @@ -1,7 +1 @@ -# Fast And Furious Showdown (EUR) - -[General] -loadSharedLibraries = false - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Fast And Furious Showdown (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010131F00.ini b/bin/gameProfiles/default/0005000010131F00.ini index 9b2dde57..b484aa82 100644 --- a/bin/gameProfiles/default/0005000010131F00.ini +++ b/bin/gameProfiles/default/0005000010131F00.ini @@ -1,4 +1 @@ -# Yoshi's Woolly World (JPN) - -[Graphics] -GPUBufferCacheAccuracy = 2 \ No newline at end of file +# Yoshi's Woolly World (JPN) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010132c00.ini b/bin/gameProfiles/default/0005000010132c00.ini index 00e83b4c..ff554b6e 100644 --- a/bin/gameProfiles/default/0005000010132c00.ini +++ b/bin/gameProfiles/default/0005000010132c00.ini @@ -1,4 +1 @@ -# Scribblenauts Unmasked: A DC Comics Adventure (US) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Scribblenauts Unmasked: A DC Comics Adventure (US) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010132d00.ini b/bin/gameProfiles/default/0005000010132d00.ini index d516cd8f..3655b674 100644 --- a/bin/gameProfiles/default/0005000010132d00.ini +++ b/bin/gameProfiles/default/0005000010132d00.ini @@ -1,4 +1 @@ -# Scribblenauts Unmasked: A DC Comics Adventure (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Scribblenauts Unmasked: A DC Comics Adventure (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010133b00.ini b/bin/gameProfiles/default/0005000010133b00.ini index 465ef364..ae2c8a48 100644 --- a/bin/gameProfiles/default/0005000010133b00.ini +++ b/bin/gameProfiles/default/0005000010133b00.ini @@ -1,4 +1 @@ -# Sniper Elite V2 (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 1 \ No newline at end of file +# Sniper Elite V2 (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010134e00.ini b/bin/gameProfiles/default/0005000010134e00.ini index e04cdd74..99ff8b41 100644 --- a/bin/gameProfiles/default/0005000010134e00.ini +++ b/bin/gameProfiles/default/0005000010134e00.ini @@ -1,4 +1 @@ -# Sniper Elite V2 (USA) - -[Graphics] -GPUBufferCacheAccuracy = 1 \ No newline at end of file +# Sniper Elite V2 (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010135500.ini b/bin/gameProfiles/default/0005000010135500.ini index cc008930..71f1c152 100644 --- a/bin/gameProfiles/default/0005000010135500.ini +++ b/bin/gameProfiles/default/0005000010135500.ini @@ -1,7 +1 @@ -# LEGO Batman 2: DC Super Heroes (EUR) - -[General] -loadSharedLibraries = false - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# LEGO Batman 2: DC Super Heroes (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010135e00.ini b/bin/gameProfiles/default/0005000010135e00.ini index ea135acc..1319dfe5 100644 --- a/bin/gameProfiles/default/0005000010135e00.ini +++ b/bin/gameProfiles/default/0005000010135e00.ini @@ -1,5 +1 @@ -# LEGO Batman 2: DC Super Heroes (USA) - -[General] -loadSharedLibraries = false -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# LEGO Batman 2: DC Super Heroes (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010136300.ini b/bin/gameProfiles/default/0005000010136300.ini index 19e3176f..b37053e0 100644 --- a/bin/gameProfiles/default/0005000010136300.ini +++ b/bin/gameProfiles/default/0005000010136300.ini @@ -1,4 +1 @@ -# BIT.TRIP Presents... Runner2: Future Legend of Rhythm Alien (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# BIT.TRIP Presents... Runner2: Future Legend of Rhythm Alien (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010136c00.ini b/bin/gameProfiles/default/0005000010136c00.ini index 8d9d5448..427a45fe 100644 --- a/bin/gameProfiles/default/0005000010136c00.ini +++ b/bin/gameProfiles/default/0005000010136c00.ini @@ -4,5 +4,4 @@ cpuMode = Singlecore-Recompiler [Graphics] -GPUBufferCacheAccuracy = 0 streamoutBufferCacheSize = 48 \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010137F00.ini b/bin/gameProfiles/default/0005000010137F00.ini index c9cddecc..151d5394 100644 --- a/bin/gameProfiles/default/0005000010137F00.ini +++ b/bin/gameProfiles/default/0005000010137F00.ini @@ -1,4 +1 @@ -# DKC: Tropical Freeze (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# DKC: Tropical Freeze (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010137c00.ini b/bin/gameProfiles/default/0005000010137c00.ini index db36989b..88fff6e7 100644 --- a/bin/gameProfiles/default/0005000010137c00.ini +++ b/bin/gameProfiles/default/0005000010137c00.ini @@ -4,5 +4,4 @@ cpuMode = Singlecore-Recompiler [Graphics] -GPUBufferCacheAccuracy = 0 streamoutBufferCacheSize = 48 \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010138300.ini b/bin/gameProfiles/default/0005000010138300.ini index 4385df2e..d992cb24 100644 --- a/bin/gameProfiles/default/0005000010138300.ini +++ b/bin/gameProfiles/default/0005000010138300.ini @@ -1,4 +1 @@ -# DKC: Tropical Freeze (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# DKC: Tropical Freeze (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010138a00.ini b/bin/gameProfiles/default/0005000010138a00.ini index 8a4f621e..26318009 100644 --- a/bin/gameProfiles/default/0005000010138a00.ini +++ b/bin/gameProfiles/default/0005000010138a00.ini @@ -1,4 +1 @@ -# Angry Birds Trilogy (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Angry Birds Trilogy (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010138f00.ini b/bin/gameProfiles/default/0005000010138f00.ini index df1f79ea..1f46d11d 100644 --- a/bin/gameProfiles/default/0005000010138f00.ini +++ b/bin/gameProfiles/default/0005000010138f00.ini @@ -1,5 +1,4 @@ # Devil's Third (JPN) [Graphics] -GPUBufferCacheAccuracy = 0 streamoutBufferCacheSize = 48 \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010140000.ini b/bin/gameProfiles/default/0005000010140000.ini index 9afff7f4..347a4481 100644 --- a/bin/gameProfiles/default/0005000010140000.ini +++ b/bin/gameProfiles/default/0005000010140000.ini @@ -1,4 +1 @@ -# Angry Birds Trilogy (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Angry Birds Trilogy (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010143200.ini b/bin/gameProfiles/default/0005000010143200.ini new file mode 100644 index 00000000..7085a558 --- /dev/null +++ b/bin/gameProfiles/default/0005000010143200.ini @@ -0,0 +1 @@ +# Cabela's Big Game Hunter: Pro Hunts (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010143500.ini b/bin/gameProfiles/default/0005000010143500.ini index a9266121..c8b93998 100644 --- a/bin/gameProfiles/default/0005000010143500.ini +++ b/bin/gameProfiles/default/0005000010143500.ini @@ -1,6 +1 @@ -# TLoZ: Wind Waker HD (USA) - -[CPU] - -[Graphics] -GPUBufferCacheAccuracy = 2 \ No newline at end of file +# TLoZ: Wind Waker HD (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010143600.ini b/bin/gameProfiles/default/0005000010143600.ini index 6ba5a4c0..6414c25d 100644 --- a/bin/gameProfiles/default/0005000010143600.ini +++ b/bin/gameProfiles/default/0005000010143600.ini @@ -1,6 +1 @@ -# TLoZ: Wind Waker HD (EUR) - -[CPU] - -[Graphics] -GPUBufferCacheAccuracy = 2 \ No newline at end of file +# TLoZ: Wind Waker HD (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010144800.ini b/bin/gameProfiles/default/0005000010144800.ini index 55a4e962..80721cd0 100644 --- a/bin/gameProfiles/default/0005000010144800.ini +++ b/bin/gameProfiles/default/0005000010144800.ini @@ -1,4 +1 @@ -# DKC: Tropical Freeze (JPN) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# DKC: Tropical Freeze (JPN) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010144f00.ini b/bin/gameProfiles/default/0005000010144f00.ini index 6bbc9e28..c2fce59a 100644 --- a/bin/gameProfiles/default/0005000010144f00.ini +++ b/bin/gameProfiles/default/0005000010144f00.ini @@ -5,4 +5,3 @@ cpuMode = Singlecore-Recompiler [Graphics] streamoutBufferCacheSize = 48 -GPUBufferCacheAccuracy = 2 \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010145000.ini b/bin/gameProfiles/default/0005000010145000.ini index f286269f..ace52dba 100644 --- a/bin/gameProfiles/default/0005000010145000.ini +++ b/bin/gameProfiles/default/0005000010145000.ini @@ -5,4 +5,3 @@ cpuMode = Singlecore-Recompiler [Graphics] streamoutBufferCacheSize = 48 -GPUBufferCacheAccuracy = 2 \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010145c00.ini b/bin/gameProfiles/default/0005000010145c00.ini index b82867e4..0be65fcc 100644 --- a/bin/gameProfiles/default/0005000010145c00.ini +++ b/bin/gameProfiles/default/0005000010145c00.ini @@ -1,7 +1,4 @@ # Super Mario 3D World (USA) -[CPU] - [Graphics] -accurateShaderMul = false -GPUBufferCacheAccuracy = 2 \ No newline at end of file +accurateShaderMul = false \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010145d00.ini b/bin/gameProfiles/default/0005000010145d00.ini index 99c70dfe..3525edd8 100644 --- a/bin/gameProfiles/default/0005000010145d00.ini +++ b/bin/gameProfiles/default/0005000010145d00.ini @@ -1,7 +1,4 @@ # Super Mario 3D World (EUR) -[CPU] - [Graphics] -accurateShaderMul = false -GPUBufferCacheAccuracy = 2 \ No newline at end of file +accurateShaderMul = false \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010147e00.ini b/bin/gameProfiles/default/0005000010147e00.ini index f5f73b9c..62109cc9 100644 --- a/bin/gameProfiles/default/0005000010147e00.ini +++ b/bin/gameProfiles/default/0005000010147e00.ini @@ -1,4 +1 @@ -# Hello Kitty Kruisers (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Hello Kitty Kruisers (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001014c100.ini b/bin/gameProfiles/default/000500001014c100.ini index da5f4d3a..64add666 100644 --- a/bin/gameProfiles/default/000500001014c100.ini +++ b/bin/gameProfiles/default/000500001014c100.ini @@ -1,4 +1 @@ -# Transformers: Rise of the Dark Spark (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Transformers: Rise of the Dark Spark (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001014c600.ini b/bin/gameProfiles/default/000500001014c600.ini index d83ea1d8..ff80f137 100644 --- a/bin/gameProfiles/default/000500001014c600.ini +++ b/bin/gameProfiles/default/000500001014c600.ini @@ -1,4 +1 @@ -# Giana Sisters Twisted Dreams (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Giana Sisters Twisted Dreams (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001014cb00.ini b/bin/gameProfiles/default/000500001014cb00.ini index 24e6e8d9..3ab3829e 100644 --- a/bin/gameProfiles/default/000500001014cb00.ini +++ b/bin/gameProfiles/default/000500001014cb00.ini @@ -1,4 +1 @@ -# Giana Sisters Twisted Dreams (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Giana Sisters Twisted Dreams (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001014d900.ini b/bin/gameProfiles/default/000500001014d900.ini index b3fae051..d234ff8a 100644 --- a/bin/gameProfiles/default/000500001014d900.ini +++ b/bin/gameProfiles/default/000500001014d900.ini @@ -1,4 +1 @@ -# PUYO PUYO TETRIS (JPN) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# PUYO PUYO TETRIS (JPN) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010154600.ini b/bin/gameProfiles/default/0005000010154600.ini index 8bdd8b98..d5af6dc0 100644 --- a/bin/gameProfiles/default/0005000010154600.ini +++ b/bin/gameProfiles/default/0005000010154600.ini @@ -4,5 +4,4 @@ cpuMode = Singlecore-Recompiler [Graphics] -GPUBufferCacheAccuracy = 0 streamoutBufferCacheSize = 48 \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001015b200.ini b/bin/gameProfiles/default/000500001015b200.ini index fd7aad16..a3872d6f 100644 --- a/bin/gameProfiles/default/000500001015b200.ini +++ b/bin/gameProfiles/default/000500001015b200.ini @@ -1,4 +1 @@ -# Child of Light (USA) - -[Graphics] -GPUBufferCacheAccuracy = 1 \ No newline at end of file +# Child of Light (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010161a00.ini b/bin/gameProfiles/default/0005000010161a00.ini index 8bd28664..88e02890 100644 --- a/bin/gameProfiles/default/0005000010161a00.ini +++ b/bin/gameProfiles/default/0005000010161a00.ini @@ -1,4 +1 @@ -# How to Train Your Dragon 2 (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# How to Train Your Dragon 2 (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010162200.ini b/bin/gameProfiles/default/0005000010162200.ini index 70e5edf4..66363dfe 100644 --- a/bin/gameProfiles/default/0005000010162200.ini +++ b/bin/gameProfiles/default/0005000010162200.ini @@ -1,4 +1 @@ -# Monkey Pirates (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Monkey Pirates (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010162a00.ini b/bin/gameProfiles/default/0005000010162a00.ini index e20011d0..3df87ebb 100644 --- a/bin/gameProfiles/default/0005000010162a00.ini +++ b/bin/gameProfiles/default/0005000010162a00.ini @@ -1,4 +1 @@ -# How to Train Your Dragon 2 (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# How to Train Your Dragon 2 (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010162b00.ini b/bin/gameProfiles/default/0005000010162b00.ini index 9802ca1d..8a50f6f6 100644 --- a/bin/gameProfiles/default/0005000010162b00.ini +++ b/bin/gameProfiles/default/0005000010162b00.ini @@ -1,6 +1 @@ -# Splatoon (JPN) - -[CPU] - -[Graphics] -GPUBufferCacheAccuracy = 2 \ No newline at end of file +# Splatoon (JPN) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001016a200.ini b/bin/gameProfiles/default/000500001016a200.ini index da6a7805..655bc980 100644 --- a/bin/gameProfiles/default/000500001016a200.ini +++ b/bin/gameProfiles/default/000500001016a200.ini @@ -1,4 +1 @@ -# Bombing Bastards (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Bombing Bastards (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001016ab00.ini b/bin/gameProfiles/default/000500001016ab00.ini index 0090ca58..594d783c 100644 --- a/bin/gameProfiles/default/000500001016ab00.ini +++ b/bin/gameProfiles/default/000500001016ab00.ini @@ -1,4 +1 @@ -# Bombing Bastards (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Bombing Bastards (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001016b200.ini b/bin/gameProfiles/default/000500001016b200.ini index 9dd87948..4db2bc79 100644 --- a/bin/gameProfiles/default/000500001016b200.ini +++ b/bin/gameProfiles/default/000500001016b200.ini @@ -6,6 +6,3 @@ useRDTSC = false [CPU] cpuTimer = cycleCounter cpuMode = Singlecore-Interpreter - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001016d400.ini b/bin/gameProfiles/default/000500001016d400.ini index 74f031ec..56c1c0f8 100644 --- a/bin/gameProfiles/default/000500001016d400.ini +++ b/bin/gameProfiles/default/000500001016d400.ini @@ -1,4 +1 @@ -# Stick It to the Man (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Stick It to the Man (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001016d800.ini b/bin/gameProfiles/default/000500001016d800.ini index 3cd2b3d0..6a8a95b8 100644 --- a/bin/gameProfiles/default/000500001016d800.ini +++ b/bin/gameProfiles/default/000500001016d800.ini @@ -1,4 +1 @@ -# Child of Light (JPN) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Child of Light (JPN) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001016da00.ini b/bin/gameProfiles/default/000500001016da00.ini index 105b4406..d54f4f50 100644 --- a/bin/gameProfiles/default/000500001016da00.ini +++ b/bin/gameProfiles/default/000500001016da00.ini @@ -2,6 +2,3 @@ [CPU] cpuMode = Singlecore-Interpreter - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001016e000.ini b/bin/gameProfiles/default/000500001016e000.ini index 871da06e..c9ef12e2 100644 --- a/bin/gameProfiles/default/000500001016e000.ini +++ b/bin/gameProfiles/default/000500001016e000.ini @@ -1,4 +1 @@ -# Stick It to the Man (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Stick It to the Man (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001016e800.ini b/bin/gameProfiles/default/000500001016e800.ini index 13482456..4e578c17 100644 --- a/bin/gameProfiles/default/000500001016e800.ini +++ b/bin/gameProfiles/default/000500001016e800.ini @@ -6,6 +6,3 @@ useRDTSC = false [CPU] cpuTimer = cycleCounter cpuMode = Singlecore-Interpreter - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001016ea00.ini b/bin/gameProfiles/default/000500001016ea00.ini index 6d72c2a2..50723312 100644 --- a/bin/gameProfiles/default/000500001016ea00.ini +++ b/bin/gameProfiles/default/000500001016ea00.ini @@ -1,4 +1 @@ -# Child of Light (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 1 \ No newline at end of file +# Child of Light (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001016fc00.ini b/bin/gameProfiles/default/000500001016fc00.ini index edd44103..9ac3ba4b 100644 --- a/bin/gameProfiles/default/000500001016fc00.ini +++ b/bin/gameProfiles/default/000500001016fc00.ini @@ -1,5 +1,4 @@ # Aqua Moto Racing Utopia (USA) -[GPU] -GPUBufferCacheAccuracy = 0 +[Graphics] streamoutBufferCacheSize = 48 \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010170100.ini b/bin/gameProfiles/default/0005000010170100.ini index 848f53ff..3de1dd34 100644 --- a/bin/gameProfiles/default/0005000010170100.ini +++ b/bin/gameProfiles/default/0005000010170100.ini @@ -1,4 +1 @@ -# Monkey Pirates (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Monkey Pirates (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010172900.ini b/bin/gameProfiles/default/0005000010172900.ini index 0414258a..5ed40dd0 100644 --- a/bin/gameProfiles/default/0005000010172900.ini +++ b/bin/gameProfiles/default/0005000010172900.ini @@ -1,5 +1,4 @@ # Aqua Moto Racing Utopia (EUR) -[GPU] -GPUBufferCacheAccuracy = 0 +[Graphics] streamoutBufferCacheSize = 48 \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010173400.ini b/bin/gameProfiles/default/0005000010173400.ini index 99995af4..c4062977 100644 --- a/bin/gameProfiles/default/0005000010173400.ini +++ b/bin/gameProfiles/default/0005000010173400.ini @@ -1,4 +1 @@ -# Transformers: Rise of the Dark Spark (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Transformers: Rise of the Dark Spark (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010176300.ini b/bin/gameProfiles/default/0005000010176300.ini index c8e0861c..30305418 100644 --- a/bin/gameProfiles/default/0005000010176300.ini +++ b/bin/gameProfiles/default/0005000010176300.ini @@ -1,5 +1,4 @@ # Little Inferno (JPN) -[CPU] +[Graphics] extendedTextureReadback = true -GPUBufferCacheAccuracy = 0 \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010176900.ini b/bin/gameProfiles/default/0005000010176900.ini index d6d36fb8..852c383a 100644 --- a/bin/gameProfiles/default/0005000010176900.ini +++ b/bin/gameProfiles/default/0005000010176900.ini @@ -1,6 +1 @@ -# Splatoon (USA) - -[CPU] - -[Graphics] -GPUBufferCacheAccuracy = 2 \ No newline at end of file +# Splatoon (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010176a00.ini b/bin/gameProfiles/default/0005000010176a00.ini index f52d1658..e1dc631b 100644 --- a/bin/gameProfiles/default/0005000010176a00.ini +++ b/bin/gameProfiles/default/0005000010176a00.ini @@ -1,6 +1 @@ -# Splatoon (EUR) - -[CPU] - -[Graphics] -GPUBufferCacheAccuracy = 2 \ No newline at end of file +# Splatoon (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010177000.ini b/bin/gameProfiles/default/0005000010177000.ini index 1c47b1dc..bc7eebf4 100644 --- a/bin/gameProfiles/default/0005000010177000.ini +++ b/bin/gameProfiles/default/0005000010177000.ini @@ -1,4 +1 @@ -# Hello Kitty Kruisers (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Hello Kitty Kruisers (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010177500.ini b/bin/gameProfiles/default/0005000010177500.ini index 74a0a58e..90be1c63 100644 --- a/bin/gameProfiles/default/0005000010177500.ini +++ b/bin/gameProfiles/default/0005000010177500.ini @@ -2,6 +2,3 @@ [CPU] cpuMode = Singlecore-Interpreter - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010177600.ini b/bin/gameProfiles/default/0005000010177600.ini index 05792513..d1b955f1 100644 --- a/bin/gameProfiles/default/0005000010177600.ini +++ b/bin/gameProfiles/default/0005000010177600.ini @@ -1,5 +1,4 @@ # Devil's Third (USA) [Graphics] -GPUBufferCacheAccuracy = 0 streamoutBufferCacheSize = 48 \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010177700.ini b/bin/gameProfiles/default/0005000010177700.ini index 072db711..e311f0ba 100644 --- a/bin/gameProfiles/default/0005000010177700.ini +++ b/bin/gameProfiles/default/0005000010177700.ini @@ -1,5 +1,4 @@ # Devil's Third (EUR) [Graphics] -GPUBufferCacheAccuracy = 0 streamoutBufferCacheSize = 48 \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001017da00.ini b/bin/gameProfiles/default/000500001017da00.ini index 6fc7282a..09b07927 100644 --- a/bin/gameProfiles/default/000500001017da00.ini +++ b/bin/gameProfiles/default/000500001017da00.ini @@ -1,4 +1 @@ -# Costume Quest 2 (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Costume Quest 2 (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001017e400.ini b/bin/gameProfiles/default/000500001017e400.ini index 562aa77a..723a374c 100644 --- a/bin/gameProfiles/default/000500001017e400.ini +++ b/bin/gameProfiles/default/000500001017e400.ini @@ -1,4 +1 @@ -# Chasing Dead (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 +# Chasing Dead (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010180500.ini b/bin/gameProfiles/default/0005000010180500.ini index d9258613..87ea51b5 100644 --- a/bin/gameProfiles/default/0005000010180500.ini +++ b/bin/gameProfiles/default/0005000010180500.ini @@ -1,7 +1,4 @@ # Captain Toad: Treasure Tracker (JPN) -[CPU] - [Graphics] accurateShaderMul = false -GPUBufferCacheAccuracy = 2 \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010180600.ini b/bin/gameProfiles/default/0005000010180600.ini index e7d7e325..8b2528e3 100644 --- a/bin/gameProfiles/default/0005000010180600.ini +++ b/bin/gameProfiles/default/0005000010180600.ini @@ -1,7 +1,4 @@ # Captain Toad: Treasure Tracker (USA) -[CPU] - [Graphics] accurateShaderMul = false -GPUBufferCacheAccuracy = 2 \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010180700.ini b/bin/gameProfiles/default/0005000010180700.ini index d0b7d792..3a7a8fe6 100644 --- a/bin/gameProfiles/default/0005000010180700.ini +++ b/bin/gameProfiles/default/0005000010180700.ini @@ -1,7 +1,4 @@ # Captain Toad: Treasure Tracker (EUR) -[CPU] - [Graphics] accurateShaderMul = false -GPUBufferCacheAccuracy = 2 \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010183000.ini b/bin/gameProfiles/default/0005000010183000.ini index 5b79f8a9..4b1c07cf 100644 --- a/bin/gameProfiles/default/0005000010183000.ini +++ b/bin/gameProfiles/default/0005000010183000.ini @@ -1,7 +1 @@ -# Runbow (USA) - - - -[Graphics] - -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Runbow (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010184900.ini b/bin/gameProfiles/default/0005000010184900.ini index 8c4d5b59..c3aac8e8 100644 --- a/bin/gameProfiles/default/0005000010184900.ini +++ b/bin/gameProfiles/default/0005000010184900.ini @@ -1,4 +1 @@ -# Slender: The Arrival (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Slender: The Arrival (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010184E00.ini b/bin/gameProfiles/default/0005000010184E00.ini index 3ca24eda..4b282824 100644 --- a/bin/gameProfiles/default/0005000010184E00.ini +++ b/bin/gameProfiles/default/0005000010184E00.ini @@ -1,6 +1 @@ -# Yoshi's Woolly World (EUR) - -[CPU] - -[Graphics] -GPUBufferCacheAccuracy = 2 \ No newline at end of file +# Yoshi's Woolly World (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010184d00.ini b/bin/gameProfiles/default/0005000010184d00.ini index 83a64a5e..b1bb76a7 100644 --- a/bin/gameProfiles/default/0005000010184d00.ini +++ b/bin/gameProfiles/default/0005000010184d00.ini @@ -1,6 +1 @@ -# Yoshi's Woolly World (USA) - -[CPU] - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Yoshi's Woolly World (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010185400.ini b/bin/gameProfiles/default/0005000010185400.ini index c69416ee..efd26cbb 100644 --- a/bin/gameProfiles/default/0005000010185400.ini +++ b/bin/gameProfiles/default/0005000010185400.ini @@ -1,6 +1 @@ -# TLoZ: Wind Waker HD (JPN) - -[CPU] - -[Graphics] -GPUBufferCacheAccuracy = 2 \ No newline at end of file +# TLoZ: Wind Waker HD (JPN) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010189f00.ini b/bin/gameProfiles/default/0005000010189f00.ini index a88c6891..ae998084 100644 --- a/bin/gameProfiles/default/0005000010189f00.ini +++ b/bin/gameProfiles/default/0005000010189f00.ini @@ -2,6 +2,3 @@ [CPU] cpuTimer = hostBased - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001018ab00.ini b/bin/gameProfiles/default/000500001018ab00.ini index 9eeef2ff..cd66a1a3 100644 --- a/bin/gameProfiles/default/000500001018ab00.ini +++ b/bin/gameProfiles/default/000500001018ab00.ini @@ -1,4 +1 @@ -# Affordable Space Adventures (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 +# Affordable Space Adventures (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001018d800.ini b/bin/gameProfiles/default/000500001018d800.ini index 0e311245..196b4aba 100644 --- a/bin/gameProfiles/default/000500001018d800.ini +++ b/bin/gameProfiles/default/000500001018d800.ini @@ -1,4 +1 @@ -# SteamWorld Dig (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# SteamWorld Dig (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001018d900.ini b/bin/gameProfiles/default/000500001018d900.ini index 4e8d8ead..779035e1 100644 --- a/bin/gameProfiles/default/000500001018d900.ini +++ b/bin/gameProfiles/default/000500001018d900.ini @@ -2,6 +2,3 @@ [General] loadSharedLibraries = false - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001018f100.ini b/bin/gameProfiles/default/000500001018f100.ini index 1a3c5fba..46ffcf0e 100644 --- a/bin/gameProfiles/default/000500001018f100.ini +++ b/bin/gameProfiles/default/000500001018f100.ini @@ -1,4 +1 @@ -# SteamWorld Dig (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# SteamWorld Dig (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001018f400.ini b/bin/gameProfiles/default/000500001018f400.ini index ecf014cf..a22052e4 100644 --- a/bin/gameProfiles/default/000500001018f400.ini +++ b/bin/gameProfiles/default/000500001018f400.ini @@ -1,4 +1 @@ -# Angry Video Game Nerd Adventures (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Angry Video Game Nerd Adventures (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001018fd00.ini b/bin/gameProfiles/default/000500001018fd00.ini index 119e00c4..eaef68fe 100644 --- a/bin/gameProfiles/default/000500001018fd00.ini +++ b/bin/gameProfiles/default/000500001018fd00.ini @@ -1,4 +1 @@ -# The Penguins of Madagascar (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# The Penguins of Madagascar (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010190300.ini b/bin/gameProfiles/default/0005000010190300.ini index b9a41d4f..fe197295 100644 --- a/bin/gameProfiles/default/0005000010190300.ini +++ b/bin/gameProfiles/default/0005000010190300.ini @@ -5,7 +5,4 @@ useRDTSC = false [CPU] cpuMode = Singlecore-Recompiler -cpuTimer = cycleCounter - -[Graphics] -GPUBufferCacheAccuracy = 1 \ No newline at end of file +cpuTimer = cycleCounter \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010193f00.ini b/bin/gameProfiles/default/0005000010193f00.ini index 9d7f8a63..104a88ca 100644 --- a/bin/gameProfiles/default/0005000010193f00.ini +++ b/bin/gameProfiles/default/0005000010193f00.ini @@ -1,4 +1 @@ -# The Penguins of Madagascar (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# The Penguins of Madagascar (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010195e00.ini b/bin/gameProfiles/default/0005000010195e00.ini index 23d72923..23585737 100644 --- a/bin/gameProfiles/default/0005000010195e00.ini +++ b/bin/gameProfiles/default/0005000010195e00.ini @@ -1,4 +1 @@ -# Rock Zombie (US) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Rock Zombie (US) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010197300.ini b/bin/gameProfiles/default/0005000010197300.ini index e15f1c7d..6f2dfa48 100644 --- a/bin/gameProfiles/default/0005000010197300.ini +++ b/bin/gameProfiles/default/0005000010197300.ini @@ -1,4 +1 @@ -# Electronic Super Joy Groove City (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Electronic Super Joy Groove City (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010197800.ini b/bin/gameProfiles/default/0005000010197800.ini index 92839df2..2af2ef33 100644 --- a/bin/gameProfiles/default/0005000010197800.ini +++ b/bin/gameProfiles/default/0005000010197800.ini @@ -1,4 +1 @@ -# Costume Quest 2 (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Costume Quest 2 (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010199e00.ini b/bin/gameProfiles/default/0005000010199e00.ini index 12c31235..01e1f2d5 100644 --- a/bin/gameProfiles/default/0005000010199e00.ini +++ b/bin/gameProfiles/default/0005000010199e00.ini @@ -1,4 +1 @@ -# High Strangeness (US) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# High Strangeness (US) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001019ab00.ini b/bin/gameProfiles/default/000500001019ab00.ini index 12c31235..01e1f2d5 100644 --- a/bin/gameProfiles/default/000500001019ab00.ini +++ b/bin/gameProfiles/default/000500001019ab00.ini @@ -1,4 +1 @@ -# High Strangeness (US) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# High Strangeness (US) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001019b000.ini b/bin/gameProfiles/default/000500001019b000.ini index 23e77a87..c458883f 100644 --- a/bin/gameProfiles/default/000500001019b000.ini +++ b/bin/gameProfiles/default/000500001019b000.ini @@ -1,4 +1 @@ -# Tachyon Project (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Tachyon Project (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001019b200.ini b/bin/gameProfiles/default/000500001019b200.ini index 6790a314..3e893f12 100644 --- a/bin/gameProfiles/default/000500001019b200.ini +++ b/bin/gameProfiles/default/000500001019b200.ini @@ -1,4 +1 @@ -# Tachyon Project (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Tachyon Project (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001019ca00.ini b/bin/gameProfiles/default/000500001019ca00.ini index 9187ed88..f79dd190 100644 --- a/bin/gameProfiles/default/000500001019ca00.ini +++ b/bin/gameProfiles/default/000500001019ca00.ini @@ -1,4 +1 @@ -# Rock Zombie (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Rock Zombie (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001019e500.ini b/bin/gameProfiles/default/000500001019e500.ini index 0ee89ea1..eec28dc9 100644 --- a/bin/gameProfiles/default/000500001019e500.ini +++ b/bin/gameProfiles/default/000500001019e500.ini @@ -1,6 +1 @@ -# TLoZ: Twilight Princess (US) - -[CPU] - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# TLoZ: Twilight Princess (US) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001019e600.ini b/bin/gameProfiles/default/000500001019e600.ini index 4f3aeecb..47380cbe 100644 --- a/bin/gameProfiles/default/000500001019e600.ini +++ b/bin/gameProfiles/default/000500001019e600.ini @@ -1,6 +1 @@ -# TLoZ: Twilight Princess (EU) - -[CPU] - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# TLoZ: Twilight Princess (EU) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001019ea00.ini b/bin/gameProfiles/default/000500001019ea00.ini index f69c7740..49250a19 100644 --- a/bin/gameProfiles/default/000500001019ea00.ini +++ b/bin/gameProfiles/default/000500001019ea00.ini @@ -1,4 +1 @@ -# Zombeer (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Zombeer (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001019ee00.ini b/bin/gameProfiles/default/000500001019ee00.ini index accf6993..958d2f84 100644 --- a/bin/gameProfiles/default/000500001019ee00.ini +++ b/bin/gameProfiles/default/000500001019ee00.ini @@ -1,4 +1 @@ -# Zombie Defense (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Zombie Defense (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101C9300.ini b/bin/gameProfiles/default/00050000101C9300.ini index f3c94e8f..09f0706d 100644 --- a/bin/gameProfiles/default/00050000101C9300.ini +++ b/bin/gameProfiles/default/00050000101C9300.ini @@ -3,4 +3,3 @@ [Graphics] disableGPUFence = false accurateShaderMul = true -GPUBufferCacheAccuracy = 2 \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101E4100.ini b/bin/gameProfiles/default/00050000101E4100.ini index 71176e83..8b8165b1 100644 --- a/bin/gameProfiles/default/00050000101E4100.ini +++ b/bin/gameProfiles/default/00050000101E4100.ini @@ -2,6 +2,3 @@ [CPU] cpuMode = Singlecore-Recompiler - -[Graphics] -GPUBufferCacheAccuracy = 1 \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101a1200.ini b/bin/gameProfiles/default/00050000101a1200.ini index 76b1207a..4ff51799 100644 --- a/bin/gameProfiles/default/00050000101a1200.ini +++ b/bin/gameProfiles/default/00050000101a1200.ini @@ -1,5 +1 @@ -# Affordable Space Adventures (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 - +# Affordable Space Adventures (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101a1800.ini b/bin/gameProfiles/default/00050000101a1800.ini index 94c50e45..56dd856c 100644 --- a/bin/gameProfiles/default/00050000101a1800.ini +++ b/bin/gameProfiles/default/00050000101a1800.ini @@ -1,4 +1 @@ -# Zombie Defense (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Zombie Defense (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101a3b00.ini b/bin/gameProfiles/default/00050000101a3b00.ini index 2efa5016..44ec4fcb 100644 --- a/bin/gameProfiles/default/00050000101a3b00.ini +++ b/bin/gameProfiles/default/00050000101a3b00.ini @@ -1,4 +1 @@ -# Life of Pixel (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Life of Pixel (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101a4300.ini b/bin/gameProfiles/default/00050000101a4300.ini index 1c49a9ab..80c72ed3 100644 --- a/bin/gameProfiles/default/00050000101a4300.ini +++ b/bin/gameProfiles/default/00050000101a4300.ini @@ -1,4 +1 @@ -# Beatbuddy (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Beatbuddy (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101a4800.ini b/bin/gameProfiles/default/00050000101a4800.ini index bb446c86..64e552e9 100644 --- a/bin/gameProfiles/default/00050000101a4800.ini +++ b/bin/gameProfiles/default/00050000101a4800.ini @@ -2,6 +2,3 @@ [General] loadSharedLibraries = false - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101a4900.ini b/bin/gameProfiles/default/00050000101a4900.ini index 74fedef3..3bb54df4 100644 --- a/bin/gameProfiles/default/00050000101a4900.ini +++ b/bin/gameProfiles/default/00050000101a4900.ini @@ -1,4 +1 @@ -# Life of Pixel (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Life of Pixel (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101a7f00.ini b/bin/gameProfiles/default/00050000101a7f00.ini index 35f91d55..be575b52 100644 --- a/bin/gameProfiles/default/00050000101a7f00.ini +++ b/bin/gameProfiles/default/00050000101a7f00.ini @@ -1,4 +1 @@ -# Shiftlings (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Shiftlings (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101a9c00.ini b/bin/gameProfiles/default/00050000101a9c00.ini index 651c8c01..6df3d13a 100644 --- a/bin/gameProfiles/default/00050000101a9c00.ini +++ b/bin/gameProfiles/default/00050000101a9c00.ini @@ -1,4 +1 @@ -# Chompy Chomp Chomp Party (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Chompy Chomp Chomp Party (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101a9e00.ini b/bin/gameProfiles/default/00050000101a9e00.ini index 5fbd157c..a8853119 100644 --- a/bin/gameProfiles/default/00050000101a9e00.ini +++ b/bin/gameProfiles/default/00050000101a9e00.ini @@ -1,4 +1 @@ -# Chompy Chomp Chomp Party (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Chompy Chomp Chomp Party (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101acc00.ini b/bin/gameProfiles/default/00050000101acc00.ini index d94071ac..6dae9607 100644 --- a/bin/gameProfiles/default/00050000101acc00.ini +++ b/bin/gameProfiles/default/00050000101acc00.ini @@ -1,4 +1 @@ -# Shiftlings (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Shiftlings (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101b0100.ini b/bin/gameProfiles/default/00050000101b0100.ini index ed2f7bf9..1599daed 100644 --- a/bin/gameProfiles/default/00050000101b0100.ini +++ b/bin/gameProfiles/default/00050000101b0100.ini @@ -1,4 +1 @@ -# Funk of Titans (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Funk of Titans (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101b4e00.ini b/bin/gameProfiles/default/00050000101b4e00.ini index 38642cbe..a0b90655 100644 --- a/bin/gameProfiles/default/00050000101b4e00.ini +++ b/bin/gameProfiles/default/00050000101b4e00.ini @@ -1,4 +1 @@ -# Funk of Titans (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Funk of Titans (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101b9900.ini b/bin/gameProfiles/default/00050000101b9900.ini index ae410226..2e83fe40 100644 --- a/bin/gameProfiles/default/00050000101b9900.ini +++ b/bin/gameProfiles/default/00050000101b9900.ini @@ -2,6 +2,3 @@ [General] loadSharedLibraries = false - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101bc300.ini b/bin/gameProfiles/default/00050000101bc300.ini index c7ec1da5..e880a0f1 100644 --- a/bin/gameProfiles/default/00050000101bc300.ini +++ b/bin/gameProfiles/default/00050000101bc300.ini @@ -1,4 +1 @@ -# Beatbuddy (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Beatbuddy (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101c3100.ini b/bin/gameProfiles/default/00050000101c3100.ini index d7c2e293..c6f5c569 100644 --- a/bin/gameProfiles/default/00050000101c3100.ini +++ b/bin/gameProfiles/default/00050000101c3100.ini @@ -1,4 +1 @@ -# Freedom Planet (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Freedom Planet (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101c4200.ini b/bin/gameProfiles/default/00050000101c4200.ini index 203ce9a7..c12944a3 100644 --- a/bin/gameProfiles/default/00050000101c4200.ini +++ b/bin/gameProfiles/default/00050000101c4200.ini @@ -1,4 +1 @@ -# The Peanuts Movie: Snoopy's Grand Adventure (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# The Peanuts Movie: Snoopy's Grand Adventure (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101c4300.ini b/bin/gameProfiles/default/00050000101c4300.ini index a2a79f38..549984d4 100644 --- a/bin/gameProfiles/default/00050000101c4300.ini +++ b/bin/gameProfiles/default/00050000101c4300.ini @@ -2,6 +2,3 @@ [CPU] cpuMode = Singlecore-Recompiler - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101c4c00.ini b/bin/gameProfiles/default/00050000101c4c00.ini index 6e8fd71f..08ad5e5b 100644 --- a/bin/gameProfiles/default/00050000101c4c00.ini +++ b/bin/gameProfiles/default/00050000101c4c00.ini @@ -5,4 +5,3 @@ cpuMode = Singlecore-Recompiler [Graphics] accurateShaderMul = false -GPUBufferCacheAccuracy = 2 \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101c4d00.ini b/bin/gameProfiles/default/00050000101c4d00.ini index 83301c0d..a1db58b0 100644 --- a/bin/gameProfiles/default/00050000101c4d00.ini +++ b/bin/gameProfiles/default/00050000101c4d00.ini @@ -5,4 +5,3 @@ cpuMode = Singlecore-Recompiler [Graphics] accurateShaderMul = false -GPUBufferCacheAccuracy = 2 \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101c6c00.ini b/bin/gameProfiles/default/00050000101c6c00.ini index da9dd712..ff16d037 100644 --- a/bin/gameProfiles/default/00050000101c6c00.ini +++ b/bin/gameProfiles/default/00050000101c6c00.ini @@ -1,4 +1 @@ -# Typoman (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Typoman (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101c7600.ini b/bin/gameProfiles/default/00050000101c7600.ini index 14128c7b..599520e4 100644 --- a/bin/gameProfiles/default/00050000101c7600.ini +++ b/bin/gameProfiles/default/00050000101c7600.ini @@ -1,4 +1 @@ -# Pumped BMX + (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Pumped BMX + (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101c7b00.ini b/bin/gameProfiles/default/00050000101c7b00.ini index 7350d0b5..9b764f96 100644 --- a/bin/gameProfiles/default/00050000101c7b00.ini +++ b/bin/gameProfiles/default/00050000101c7b00.ini @@ -1,4 +1 @@ -# Chronicles of Teddy: Harmony of Exidus (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Chronicles of Teddy: Harmony of Exidus (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101c7d00.ini b/bin/gameProfiles/default/00050000101c7d00.ini index 45ce4448..60a0dd23 100644 --- a/bin/gameProfiles/default/00050000101c7d00.ini +++ b/bin/gameProfiles/default/00050000101c7d00.ini @@ -1,4 +1 @@ -# Pumped BMX + (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Pumped BMX + (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101c9400.ini b/bin/gameProfiles/default/00050000101c9400.ini index 86c1b839..585a9e6f 100644 --- a/bin/gameProfiles/default/00050000101c9400.ini +++ b/bin/gameProfiles/default/00050000101c9400.ini @@ -3,4 +3,3 @@ [Graphics] disableGPUFence = false accurateShaderMul = true -GPUBufferCacheAccuracy = 2 \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101c9500.ini b/bin/gameProfiles/default/00050000101c9500.ini index 4f326b32..71485002 100644 --- a/bin/gameProfiles/default/00050000101c9500.ini +++ b/bin/gameProfiles/default/00050000101c9500.ini @@ -3,4 +3,3 @@ [Graphics] disableGPUFence = false accurateShaderMul = true -GPUBufferCacheAccuracy = 2 \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101c9a00.ini b/bin/gameProfiles/default/00050000101c9a00.ini index 0cc7525b..026e593f 100644 --- a/bin/gameProfiles/default/00050000101c9a00.ini +++ b/bin/gameProfiles/default/00050000101c9a00.ini @@ -2,6 +2,3 @@ [CPU] cpuMode = Singlecore-Recompiler - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101cc900.ini b/bin/gameProfiles/default/00050000101cc900.ini index dded48b2..ceaa7e67 100644 --- a/bin/gameProfiles/default/00050000101cc900.ini +++ b/bin/gameProfiles/default/00050000101cc900.ini @@ -1,4 +1 @@ -# Freedom Planet (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Freedom Planet (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101ccf00.ini b/bin/gameProfiles/default/00050000101ccf00.ini index e71dfd8f..d3d497f1 100644 --- a/bin/gameProfiles/default/00050000101ccf00.ini +++ b/bin/gameProfiles/default/00050000101ccf00.ini @@ -1,4 +1 @@ -# Never Alone (Kisima Ingitchuna) (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Never Alone (Kisima Ingitchuna) (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101ce000.ini b/bin/gameProfiles/default/00050000101ce000.ini index 69aa9dae..30a271e8 100644 --- a/bin/gameProfiles/default/00050000101ce000.ini +++ b/bin/gameProfiles/default/00050000101ce000.ini @@ -1,4 +1 @@ -# Typoman (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Typoman (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101ce800.ini b/bin/gameProfiles/default/00050000101ce800.ini index 2cc75f8e..902e8e23 100644 --- a/bin/gameProfiles/default/00050000101ce800.ini +++ b/bin/gameProfiles/default/00050000101ce800.ini @@ -1,4 +1 @@ -# Never Alone (Kisima Ingitchuna) (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Never Alone (Kisima Ingitchuna) (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101d2100.ini b/bin/gameProfiles/default/00050000101d2100.ini index caac5cdc..830f5f81 100644 --- a/bin/gameProfiles/default/00050000101d2100.ini +++ b/bin/gameProfiles/default/00050000101d2100.ini @@ -1,5 +1,4 @@ # Little Inferno (US) -[CPU] +[Graphics] extendedTextureReadback = true -GPUBufferCacheAccuracy = 0 \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101d4500.ini b/bin/gameProfiles/default/00050000101d4500.ini index 8ae9fc73..c8244324 100644 --- a/bin/gameProfiles/default/00050000101d4500.ini +++ b/bin/gameProfiles/default/00050000101d4500.ini @@ -1,4 +1 @@ -# Grumpy Reaper (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Grumpy Reaper (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101d4d00.ini b/bin/gameProfiles/default/00050000101d4d00.ini index 5df2ddbb..23887c1f 100644 --- a/bin/gameProfiles/default/00050000101d4d00.ini +++ b/bin/gameProfiles/default/00050000101d4d00.ini @@ -1,4 +1 @@ -# Joe's Diner (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Joe's Diner (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101d5000.ini b/bin/gameProfiles/default/00050000101d5000.ini index 2e1b8356..4cff3852 100644 --- a/bin/gameProfiles/default/00050000101d5000.ini +++ b/bin/gameProfiles/default/00050000101d5000.ini @@ -1,4 +1 @@ -# The Peanuts Movie: Snoopy's Grand Adventure (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# The Peanuts Movie: Snoopy's Grand Adventure (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101d5500.ini b/bin/gameProfiles/default/00050000101d5500.ini index 81bcef30..2e1f7542 100644 --- a/bin/gameProfiles/default/00050000101d5500.ini +++ b/bin/gameProfiles/default/00050000101d5500.ini @@ -1,4 +1 @@ -# Joe's Diner (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Joe's Diner (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101d6000.ini b/bin/gameProfiles/default/00050000101d6000.ini index 129477c2..09ff9c3c 100644 --- a/bin/gameProfiles/default/00050000101d6000.ini +++ b/bin/gameProfiles/default/00050000101d6000.ini @@ -2,6 +2,3 @@ [CPU] cpuMode = Singlecore-Recompiler - -[Graphics] -GPUBufferCacheAccuracy = 1 \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101d6d00.ini b/bin/gameProfiles/default/00050000101d6d00.ini index 0bf677ba..a04e39c7 100644 --- a/bin/gameProfiles/default/00050000101d6d00.ini +++ b/bin/gameProfiles/default/00050000101d6d00.ini @@ -1,7 +1 @@ -# Runbow (EUR) - - - -[Graphics] - -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Runbow (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101d7500.ini b/bin/gameProfiles/default/00050000101d7500.ini index 8707efcd..992b00cc 100644 --- a/bin/gameProfiles/default/00050000101d7500.ini +++ b/bin/gameProfiles/default/00050000101d7500.ini @@ -2,6 +2,3 @@ [General] loadSharedLibraries = false - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101d8900.ini b/bin/gameProfiles/default/00050000101d8900.ini index 29b9698f..aaf7d122 100644 --- a/bin/gameProfiles/default/00050000101d8900.ini +++ b/bin/gameProfiles/default/00050000101d8900.ini @@ -1,4 +1 @@ -# Slender: The Arrival (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Slender: The Arrival (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101d8d00.ini b/bin/gameProfiles/default/00050000101d8d00.ini index 864c446b..0b61b998 100644 --- a/bin/gameProfiles/default/00050000101d8d00.ini +++ b/bin/gameProfiles/default/00050000101d8d00.ini @@ -1,4 +1 @@ -# Rock 'N Racing Off Road DX (USA) - -[Graphics] -GPUBufferCacheAccuracy = 1 \ No newline at end of file +# Rock 'N Racing Off Road DX (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101d9600.ini b/bin/gameProfiles/default/00050000101d9600.ini index c2c62b6a..aa4f9a10 100644 --- a/bin/gameProfiles/default/00050000101d9600.ini +++ b/bin/gameProfiles/default/00050000101d9600.ini @@ -1,4 +1 @@ -# Rock 'N Racing Off Road DX (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 1 \ No newline at end of file +# Rock 'N Racing Off Road DX (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101d9d00.ini b/bin/gameProfiles/default/00050000101d9d00.ini index dc54dea2..30d07833 100644 --- a/bin/gameProfiles/default/00050000101d9d00.ini +++ b/bin/gameProfiles/default/00050000101d9d00.ini @@ -2,6 +2,3 @@ [General] loadSharedLibraries = false - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101dac00.ini b/bin/gameProfiles/default/00050000101dac00.ini index 1780613f..bb988dac 100644 --- a/bin/gameProfiles/default/00050000101dac00.ini +++ b/bin/gameProfiles/default/00050000101dac00.ini @@ -1,4 +1 @@ -# Swap Fire - -[GPU] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Swap Fire \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101daf00.ini b/bin/gameProfiles/default/00050000101daf00.ini index 2c8bef7b..3ebc182e 100644 --- a/bin/gameProfiles/default/00050000101daf00.ini +++ b/bin/gameProfiles/default/00050000101daf00.ini @@ -1,4 +1 @@ -# Chronicles of Teddy: Harmony of Exidus (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Chronicles of Teddy: Harmony of Exidus (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101db000.ini b/bin/gameProfiles/default/00050000101db000.ini index 94736dbb..fafb6333 100644 --- a/bin/gameProfiles/default/00050000101db000.ini +++ b/bin/gameProfiles/default/00050000101db000.ini @@ -1,4 +1 @@ -# Oddworld New 'n' Tasty (US) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Oddworld New 'n' Tasty (US) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101dbb00.ini b/bin/gameProfiles/default/00050000101dbb00.ini index 092b54ec..7e08923d 100644 --- a/bin/gameProfiles/default/00050000101dbb00.ini +++ b/bin/gameProfiles/default/00050000101dbb00.ini @@ -1,4 +1 @@ -# Oddworld New 'n' Tasty (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Oddworld New 'n' Tasty (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101dbc00.ini b/bin/gameProfiles/default/00050000101dbc00.ini index 98c41e22..94808fc1 100644 --- a/bin/gameProfiles/default/00050000101dbc00.ini +++ b/bin/gameProfiles/default/00050000101dbc00.ini @@ -1,4 +1 @@ -# Star Ghost (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Star Ghost (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101dbe00.ini b/bin/gameProfiles/default/00050000101dbe00.ini index 66ec5de9..0145c649 100644 --- a/bin/gameProfiles/default/00050000101dbe00.ini +++ b/bin/gameProfiles/default/00050000101dbe00.ini @@ -1,7 +1,4 @@ # Minecraft: Wii U Edition (JPN) [General] -loadSharedLibraries = false - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +loadSharedLibraries = false \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101dbf00.ini b/bin/gameProfiles/default/00050000101dbf00.ini index 6f32b59d..6cab37ad 100644 --- a/bin/gameProfiles/default/00050000101dbf00.ini +++ b/bin/gameProfiles/default/00050000101dbf00.ini @@ -1,4 +1 @@ -# Angry Video Game Nerd Adventures (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Angry Video Game Nerd Adventures (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101dc000.ini b/bin/gameProfiles/default/00050000101dc000.ini index b4b8717c..8734af28 100644 --- a/bin/gameProfiles/default/00050000101dc000.ini +++ b/bin/gameProfiles/default/00050000101dc000.ini @@ -1,4 +1 @@ -# Vektor Wars (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Vektor Wars (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101dc200.ini b/bin/gameProfiles/default/00050000101dc200.ini index 0cec8b6d..eebe3ac5 100644 --- a/bin/gameProfiles/default/00050000101dc200.ini +++ b/bin/gameProfiles/default/00050000101dc200.ini @@ -1,4 +1 @@ -# Vektor Wars (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Vektor Wars (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101dd000.ini b/bin/gameProfiles/default/00050000101dd000.ini index 8f275d8c..33caf468 100644 --- a/bin/gameProfiles/default/00050000101dd000.ini +++ b/bin/gameProfiles/default/00050000101dd000.ini @@ -1,4 +1 @@ -# Star Ghost (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Star Ghost (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101dd600.ini b/bin/gameProfiles/default/00050000101dd600.ini index 7b180555..1a17ec4b 100644 --- a/bin/gameProfiles/default/00050000101dd600.ini +++ b/bin/gameProfiles/default/00050000101dd600.ini @@ -1,4 +1 @@ -# BIT.TRIP Presents... Runner2: Future Legend of Rhythm Alien (JPN) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# BIT.TRIP Presents... Runner2: Future Legend of Rhythm Alien (JPN) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101dd700.ini b/bin/gameProfiles/default/00050000101dd700.ini index 57b3a897..fbefda0e 100644 --- a/bin/gameProfiles/default/00050000101dd700.ini +++ b/bin/gameProfiles/default/00050000101dd700.ini @@ -1,7 +1 @@ -# Runbow (JPN) - - - -[Graphics] - -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Runbow (JPN) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101ddf00.ini b/bin/gameProfiles/default/00050000101ddf00.ini index a3adf2fc..5c802484 100644 --- a/bin/gameProfiles/default/00050000101ddf00.ini +++ b/bin/gameProfiles/default/00050000101ddf00.ini @@ -1,4 +1 @@ -# Hive Jump (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Hive Jump (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101e0100.ini b/bin/gameProfiles/default/00050000101e0100.ini index 13f74180..738553d8 100644 --- a/bin/gameProfiles/default/00050000101e0100.ini +++ b/bin/gameProfiles/default/00050000101e0100.ini @@ -1,6 +1 @@ -# Minecraft: Story Mode (USA) - - - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Minecraft: Story Mode (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101e1800.ini b/bin/gameProfiles/default/00050000101e1800.ini index bf35ca87..a372c127 100644 --- a/bin/gameProfiles/default/00050000101e1800.ini +++ b/bin/gameProfiles/default/00050000101e1800.ini @@ -1,4 +1 @@ -# Human Resource Machine (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Human Resource Machine (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101e1a00.ini b/bin/gameProfiles/default/00050000101e1a00.ini index 23dca6a5..a90125c4 100644 --- a/bin/gameProfiles/default/00050000101e1a00.ini +++ b/bin/gameProfiles/default/00050000101e1a00.ini @@ -1,4 +1 @@ -# Human Resource Machine (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Human Resource Machine (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101e1b00.ini b/bin/gameProfiles/default/00050000101e1b00.ini index 5675969a..88e9b456 100644 --- a/bin/gameProfiles/default/00050000101e1b00.ini +++ b/bin/gameProfiles/default/00050000101e1b00.ini @@ -2,6 +2,3 @@ [CPU] cpuTimer = hostBased - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101e3800.ini b/bin/gameProfiles/default/00050000101e3800.ini index 4e6f4859..fdfa2cdf 100644 --- a/bin/gameProfiles/default/00050000101e3800.ini +++ b/bin/gameProfiles/default/00050000101e3800.ini @@ -1,7 +1 @@ -# Dual Core (USA) - -[General] -loadSharedLibraries = false - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Dual Core (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101e4200.ini b/bin/gameProfiles/default/00050000101e4200.ini index 9e6a983b..ef94b291 100644 --- a/bin/gameProfiles/default/00050000101e4200.ini +++ b/bin/gameProfiles/default/00050000101e4200.ini @@ -6,6 +6,3 @@ useRDTSC = false [CPU] cpuTimer = cycleCounter cpuMode = Singlecore-Interpreter - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101e5300.ini b/bin/gameProfiles/default/00050000101e5300.ini index c6f6674a..c04cd6b6 100644 --- a/bin/gameProfiles/default/00050000101e5300.ini +++ b/bin/gameProfiles/default/00050000101e5300.ini @@ -6,6 +6,3 @@ useRDTSC = false [CPU] cpuMode = Singlecore-Recompiler cpuTimer = cycleCounter - -[Graphics] -GPUBufferCacheAccuracy = 1 \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101e5400.ini b/bin/gameProfiles/default/00050000101e5400.ini index 299c9e40..221a23ed 100644 --- a/bin/gameProfiles/default/00050000101e5400.ini +++ b/bin/gameProfiles/default/00050000101e5400.ini @@ -6,6 +6,3 @@ useRDTSC = false [CPU] cpuMode = Singlecore-Recompiler cpuTimer = cycleCounter - -[Graphics] -GPUBufferCacheAccuracy = 1 \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101e5e00.ini b/bin/gameProfiles/default/00050000101e5e00.ini index 2736143b..ab9fc348 100644 --- a/bin/gameProfiles/default/00050000101e5e00.ini +++ b/bin/gameProfiles/default/00050000101e5e00.ini @@ -1,4 +1 @@ -# Chasing Dead (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 +# Chasing Dead (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101e7300.ini b/bin/gameProfiles/default/00050000101e7300.ini index de2d9ace..092720b8 100644 --- a/bin/gameProfiles/default/00050000101e7300.ini +++ b/bin/gameProfiles/default/00050000101e7300.ini @@ -1,4 +1 @@ -# The Deer God (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# The Deer God (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101e7400.ini b/bin/gameProfiles/default/00050000101e7400.ini index 38a64064..e8644aa7 100644 --- a/bin/gameProfiles/default/00050000101e7400.ini +++ b/bin/gameProfiles/default/00050000101e7400.ini @@ -1,4 +1 @@ -# Grumpy Reaper (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Grumpy Reaper (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101e9300.ini b/bin/gameProfiles/default/00050000101e9300.ini index a88c29bc..24c0dad8 100644 --- a/bin/gameProfiles/default/00050000101e9300.ini +++ b/bin/gameProfiles/default/00050000101e9300.ini @@ -1,4 +1 @@ -# Gear Gauntlet (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Gear Gauntlet (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101e9400.ini b/bin/gameProfiles/default/00050000101e9400.ini index 6f914578..6b78201e 100644 --- a/bin/gameProfiles/default/00050000101e9400.ini +++ b/bin/gameProfiles/default/00050000101e9400.ini @@ -1,4 +1 @@ -# Gear Gauntlet (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Gear Gauntlet (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101eb300.ini b/bin/gameProfiles/default/00050000101eb300.ini index e5b62760..66c8dcb4 100644 --- a/bin/gameProfiles/default/00050000101eb300.ini +++ b/bin/gameProfiles/default/00050000101eb300.ini @@ -1,4 +1 @@ -# The Beggar's Ride (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# The Beggar's Ride (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101ec700.ini b/bin/gameProfiles/default/00050000101ec700.ini index 27e0f560..7dd85123 100644 --- a/bin/gameProfiles/default/00050000101ec700.ini +++ b/bin/gameProfiles/default/00050000101ec700.ini @@ -1,4 +1 @@ -# The Beggar's Ride (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# The Beggar's Ride (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101ecf00.ini b/bin/gameProfiles/default/00050000101ecf00.ini index 3191607c..e3b80181 100644 --- a/bin/gameProfiles/default/00050000101ecf00.ini +++ b/bin/gameProfiles/default/00050000101ecf00.ini @@ -1,4 +1 @@ -# Buddy & Me Dream Edition (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Buddy & Me Dream Edition (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101f1300.ini b/bin/gameProfiles/default/00050000101f1300.ini index 3b17b3a5..85683631 100644 --- a/bin/gameProfiles/default/00050000101f1300.ini +++ b/bin/gameProfiles/default/00050000101f1300.ini @@ -1,4 +1 @@ -# Armikrog (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Armikrog (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101f2800.ini b/bin/gameProfiles/default/00050000101f2800.ini index 65c08d62..a8d455dd 100644 --- a/bin/gameProfiles/default/00050000101f2800.ini +++ b/bin/gameProfiles/default/00050000101f2800.ini @@ -1,7 +1,4 @@ # 8Bit Hero (USA) -[Graphics] -GPUBufferCacheAccuracy = 0 - [CPU] cpuMode = Singlecore-Interpreter \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101f4a00.ini b/bin/gameProfiles/default/00050000101f4a00.ini index 2d9432da..e0ca60b7 100644 --- a/bin/gameProfiles/default/00050000101f4a00.ini +++ b/bin/gameProfiles/default/00050000101f4a00.ini @@ -1,4 +1 @@ -# Buddy & Me Dream Edition (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Buddy & Me Dream Edition (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101f5700.ini b/bin/gameProfiles/default/00050000101f5700.ini index a2d5119f..c0c98988 100644 --- a/bin/gameProfiles/default/00050000101f5700.ini +++ b/bin/gameProfiles/default/00050000101f5700.ini @@ -1,4 +1 @@ -# Jotun Valhalla Edition (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Jotun Valhalla Edition (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101f6f00.ini b/bin/gameProfiles/default/00050000101f6f00.ini index 92bf8b9e..4a590788 100644 --- a/bin/gameProfiles/default/00050000101f6f00.ini +++ b/bin/gameProfiles/default/00050000101f6f00.ini @@ -1,4 +1 @@ -# Jotun Valhalla Edition (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Jotun Valhalla Edition (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101f7600.ini b/bin/gameProfiles/default/00050000101f7600.ini index 88e55d2a..bbe32dff 100644 --- a/bin/gameProfiles/default/00050000101f7600.ini +++ b/bin/gameProfiles/default/00050000101f7600.ini @@ -1,7 +1 @@ -# Dual Core (EUR) - -[General] -loadSharedLibraries = false - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Dual Core (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101f9700.ini b/bin/gameProfiles/default/00050000101f9700.ini index 34c46581..a36f67a1 100644 --- a/bin/gameProfiles/default/00050000101f9700.ini +++ b/bin/gameProfiles/default/00050000101f9700.ini @@ -1,4 +1 @@ -# Darksiders Warmastered Edition (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Darksiders Warmastered Edition (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101fa600.ini b/bin/gameProfiles/default/00050000101fa600.ini index 89ab8ade..653531f9 100644 --- a/bin/gameProfiles/default/00050000101fa600.ini +++ b/bin/gameProfiles/default/00050000101fa600.ini @@ -1,4 +1 @@ -# Darksiders Warmastered Edition (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Darksiders Warmastered Edition (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101fd100.ini b/bin/gameProfiles/default/00050000101fd100.ini index 6ce5a608..a0f02db2 100644 --- a/bin/gameProfiles/default/00050000101fd100.ini +++ b/bin/gameProfiles/default/00050000101fd100.ini @@ -1,4 +1 @@ -# Grumpy Reaper (JPN) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Grumpy Reaper (JPN) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101ff200.ini b/bin/gameProfiles/default/00050000101ff200.ini index 54e13b65..13b5470b 100644 --- a/bin/gameProfiles/default/00050000101ff200.ini +++ b/bin/gameProfiles/default/00050000101ff200.ini @@ -1,4 +1 @@ -# Exile's End (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Exile's End (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101ffc00.ini b/bin/gameProfiles/default/00050000101ffc00.ini index e01c407c..4d6850ae 100644 --- a/bin/gameProfiles/default/00050000101ffc00.ini +++ b/bin/gameProfiles/default/00050000101ffc00.ini @@ -1,5 +1,4 @@ # Ghost Blade HD (USA) [Graphics] -GPUBufferCacheAccuracy = 0 streamoutBufferCacheSize = 48 \ No newline at end of file diff --git a/bin/gameProfiles/default/00050000101ffe00.ini b/bin/gameProfiles/default/00050000101ffe00.ini index 9225f393..123cc4b9 100644 --- a/bin/gameProfiles/default/00050000101ffe00.ini +++ b/bin/gameProfiles/default/00050000101ffe00.ini @@ -1,4 +1 @@ -# Tetrimos (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Tetrimos (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010200300.ini b/bin/gameProfiles/default/0005000010200300.ini index 47600923..b62d3c32 100644 --- a/bin/gameProfiles/default/0005000010200300.ini +++ b/bin/gameProfiles/default/0005000010200300.ini @@ -1,4 +1 @@ -# Armikrog (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Armikrog (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010200b00.ini b/bin/gameProfiles/default/0005000010200b00.ini index 8fc9da4b..7a6469b5 100644 --- a/bin/gameProfiles/default/0005000010200b00.ini +++ b/bin/gameProfiles/default/0005000010200b00.ini @@ -1,4 +1 @@ -# Tetrimos (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Tetrimos (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010204a00.ini b/bin/gameProfiles/default/0005000010204a00.ini index 8a0285c3..e0d9db5a 100644 --- a/bin/gameProfiles/default/0005000010204a00.ini +++ b/bin/gameProfiles/default/0005000010204a00.ini @@ -1,4 +1 @@ -# Exile's End (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Exile's End (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010207300.ini b/bin/gameProfiles/default/0005000010207300.ini index c678e7d6..56d9a42f 100644 --- a/bin/gameProfiles/default/0005000010207300.ini +++ b/bin/gameProfiles/default/0005000010207300.ini @@ -1,4 +1 @@ -# Koi DX (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Koi DX (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010207500.ini b/bin/gameProfiles/default/0005000010207500.ini index 090be3f2..1a4ab56d 100644 --- a/bin/gameProfiles/default/0005000010207500.ini +++ b/bin/gameProfiles/default/0005000010207500.ini @@ -1,4 +1 @@ -# Koi DX (USA) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Koi DX (USA) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001020a200.ini b/bin/gameProfiles/default/000500001020a200.ini index bef0c82e..6960a967 100644 --- a/bin/gameProfiles/default/000500001020a200.ini +++ b/bin/gameProfiles/default/000500001020a200.ini @@ -1,5 +1 @@ -# Minecraft: Story Mode (EUR) - - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Minecraft: Story Mode (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/000500001020b600.ini b/bin/gameProfiles/default/000500001020b600.ini index 74528c38..46e4c8da 100644 --- a/bin/gameProfiles/default/000500001020b600.ini +++ b/bin/gameProfiles/default/000500001020b600.ini @@ -1,5 +1,4 @@ # Ghost Blade HD (EUR) [Graphics] -GPUBufferCacheAccuracy = 0 streamoutBufferCacheSize = 48 \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000010211b00.ini b/bin/gameProfiles/default/0005000010211b00.ini index 69534194..7e82f408 100644 --- a/bin/gameProfiles/default/0005000010211b00.ini +++ b/bin/gameProfiles/default/0005000010211b00.ini @@ -1,4 +1 @@ -# Sphere Slice (EUR) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# Sphere Slice (EUR) \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000C1012BC00.ini b/bin/gameProfiles/default/0005000C1012BC00.ini index 5c2c09d4..5f699eb6 100644 --- a/bin/gameProfiles/default/0005000C1012BC00.ini +++ b/bin/gameProfiles/default/0005000C1012BC00.ini @@ -1,8 +1,4 @@ # Pikmin 3 (JAP) - - [Graphics] - extendedTextureReadback = true -GPUBufferCacheAccuracy = 2 \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000C1012BD00.ini b/bin/gameProfiles/default/0005000C1012BD00.ini index 8ab10175..cd27ff77 100644 --- a/bin/gameProfiles/default/0005000C1012BD00.ini +++ b/bin/gameProfiles/default/0005000C1012BD00.ini @@ -1,8 +1,4 @@ # Pikmin 3 (USA) - - [Graphics] - extendedTextureReadback = true -GPUBufferCacheAccuracy = 2 \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000C1012BE00.ini b/bin/gameProfiles/default/0005000C1012BE00.ini index e7226ef4..6be6a929 100644 --- a/bin/gameProfiles/default/0005000C1012BE00.ini +++ b/bin/gameProfiles/default/0005000C1012BE00.ini @@ -1,8 +1,4 @@ # Pikmin 3 (EU) - - [Graphics] - extendedTextureReadback = true -GPUBufferCacheAccuracy = 2 \ No newline at end of file diff --git a/bin/gameProfiles/default/0005000e1019c800.ini b/bin/gameProfiles/default/0005000e1019c800.ini index 8c47898c..81adc4c9 100644 --- a/bin/gameProfiles/default/0005000e1019c800.ini +++ b/bin/gameProfiles/default/0005000e1019c800.ini @@ -1,4 +1 @@ -# TLoZ: Twilight Princess (JPN) - -[Graphics] -GPUBufferCacheAccuracy = 0 \ No newline at end of file +# TLoZ: Twilight Princess (JPN) \ No newline at end of file From 1bcc064593545ff3603521f24e7d32c8b8adabab Mon Sep 17 00:00:00 2001 From: Tillsunset <35825944+Tillsunset@users.noreply.github.com> Date: Sun, 23 Oct 2022 06:06:20 -0500 Subject: [PATCH 014/589] Add check for "." in FSC path (#402) --- src/Cafe/Filesystem/FST/fstUtil.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Cafe/Filesystem/FST/fstUtil.h b/src/Cafe/Filesystem/FST/fstUtil.h index 4ea9465d..01283684 100644 --- a/src/Cafe/Filesystem/FST/fstUtil.h +++ b/src/Cafe/Filesystem/FST/fstUtil.h @@ -28,6 +28,8 @@ class FSCPath { if (m_names.size() > 0xFFFF) return; + if (nameLen == 1 && *name == '.') + return; m_nodes.emplace_back((uint16)m_names.size(), nameLen); m_names.insert(m_names.end(), name, name + nameLen); } @@ -297,6 +299,12 @@ static void FSTPathUnitTest() cemu_assert_debug(p6.GetNodeCount() == 0); p6 = FSCPath("/////////////"); cemu_assert_debug(p6.GetNodeCount() == 0); + // test 7 - periods in path + FSCPath p7("/vol/content/./.."); + cemu_assert_debug(p7.GetNodeCount() == 3); + cemu_assert_debug(p7.MatchNodeName(0, "vol")); + cemu_assert_debug(p7.MatchNodeName(1, "content")); + cemu_assert_debug(p7.MatchNodeName(2, "..")); } From c40466f3a8d12a34ca1a82b596af18dd56a3ec2b Mon Sep 17 00:00:00 2001 From: Jeremy Kescher Date: Sun, 23 Oct 2022 12:03:51 +0000 Subject: [PATCH 015/589] Fix incorrect title ID (00050000-1011000? -> 00050000-10111000) (#404) --- .../default/{000500001011000.ini => 0005000010111000.ini} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename bin/gameProfiles/default/{000500001011000.ini => 0005000010111000.ini} (100%) diff --git a/bin/gameProfiles/default/000500001011000.ini b/bin/gameProfiles/default/0005000010111000.ini similarity index 100% rename from bin/gameProfiles/default/000500001011000.ini rename to bin/gameProfiles/default/0005000010111000.ini From 028b3f79926a280b1a6fc5abbd438cc875079b89 Mon Sep 17 00:00:00 2001 From: Exzap <13877693+Exzap@users.noreply.github.com> Date: Sun, 23 Oct 2022 15:47:42 +0200 Subject: [PATCH 016/589] Make controller button code thread-safe (#405) * Refactor spinlock to meet Lockable requirements * Input: Refactor button code and make it thread-safe --- .../HW/Espresso/Debugger/DebugSymbolStorage.h | 14 +-- src/Cafe/HW/Espresso/PPCTimer.cpp | 4 +- .../HW/Espresso/Recompiler/PPCRecompiler.cpp | 36 +++--- src/Cafe/HW/Latte/Core/FetchShader.cpp | 10 +- src/Cafe/HW/Latte/Core/LatteBufferCache.cpp | 8 +- .../HW/Latte/Renderer/Vulkan/CachedFBOVk.h | 8 +- .../Latte/Renderer/Vulkan/RendererShaderVk.h | 8 +- .../Vulkan/VulkanPipelineStableCache.cpp | 24 ++-- .../Latte/Renderer/Vulkan/VulkanRenderer.cpp | 12 +- src/Cafe/IOSU/kernel/iosu_kernel.cpp | 14 +-- .../OS/libs/coreinit/coreinit_Callbacks.cpp | 18 +-- .../OS/libs/coreinit/coreinit_MPQueue.cpp | 8 +- .../coreinit/coreinit_Synchronization.cpp | 4 +- src/Cafe/OS/libs/snd_core/ax_ist.cpp | 4 +- src/Cafe/OS/libs/snd_core/ax_voice.cpp | 12 +- src/gui/guiWrapper.h | 14 +-- src/gui/input/InputSettings2.cpp | 2 +- src/gui/input/panels/InputPanel.cpp | 110 ++++++++--------- src/input/api/Controller.cpp | 24 ++-- src/input/api/ControllerState.h | 111 +++++++++++++++++- src/input/api/DSU/DSUController.cpp | 6 +- .../api/DirectInput/DirectInputController.cpp | 23 ++-- src/input/api/Keyboard/KeyboardController.cpp | 7 +- src/input/api/SDL/SDLController.cpp | 4 +- .../api/Wiimote/NativeWiimoteController.cpp | 13 +- src/input/api/XInput/XInputController.cpp | 2 +- src/input/emulated/EmulatedController.cpp | 8 +- src/util/helpers/fspinlock.h | 23 ++-- 28 files changed, 311 insertions(+), 220 deletions(-) diff --git a/src/Cafe/HW/Espresso/Debugger/DebugSymbolStorage.h b/src/Cafe/HW/Espresso/Debugger/DebugSymbolStorage.h index 0d7b7d49..aba6a9b5 100644 --- a/src/Cafe/HW/Espresso/Debugger/DebugSymbolStorage.h +++ b/src/Cafe/HW/Espresso/Debugger/DebugSymbolStorage.h @@ -24,28 +24,28 @@ class DebugSymbolStorage public: static void StoreDataType(MPTR address, DEBUG_SYMBOL_TYPE type) { - s_lock.acquire(); + s_lock.lock(); s_typeStorage[address] = type; - s_lock.release(); + s_lock.unlock(); } static DEBUG_SYMBOL_TYPE GetDataType(MPTR address) { - s_lock.acquire(); + s_lock.lock(); auto itr = s_typeStorage.find(address); if (itr == s_typeStorage.end()) { - s_lock.release(); + s_lock.unlock(); return DEBUG_SYMBOL_TYPE::UNDEFINED; } DEBUG_SYMBOL_TYPE t = itr->second; - s_lock.release(); + s_lock.unlock(); return t; } static void ClearRange(MPTR address, uint32 length) { - s_lock.acquire(); + s_lock.lock(); while (length > 0) { auto itr = s_typeStorage.find(address); @@ -54,7 +54,7 @@ public: address += 4; length -= 4; } - s_lock.release(); + s_lock.unlock(); } private: diff --git a/src/Cafe/HW/Espresso/PPCTimer.cpp b/src/Cafe/HW/Espresso/PPCTimer.cpp index 36198dac..153458d8 100644 --- a/src/Cafe/HW/Espresso/PPCTimer.cpp +++ b/src/Cafe/HW/Espresso/PPCTimer.cpp @@ -129,7 +129,7 @@ FSpinlock sTimerSpinlock; // thread safe uint64 PPCTimer_getFromRDTSC() { - sTimerSpinlock.acquire(); + sTimerSpinlock.lock(); _mm_mfence(); uint64 rdtscCurrentMeasure = __rdtsc(); uint64 rdtscDif = rdtscCurrentMeasure - _rdtscLastMeasure; @@ -165,6 +165,6 @@ uint64 PPCTimer_getFromRDTSC() _tickSummary += elapsedTick; - sTimerSpinlock.release(); + sTimerSpinlock.unlock(); return _tickSummary; } diff --git a/src/Cafe/HW/Espresso/Recompiler/PPCRecompiler.cpp b/src/Cafe/HW/Espresso/Recompiler/PPCRecompiler.cpp index 98263ff3..588e5397 100644 --- a/src/Cafe/HW/Espresso/Recompiler/PPCRecompiler.cpp +++ b/src/Cafe/HW/Espresso/Recompiler/PPCRecompiler.cpp @@ -47,20 +47,20 @@ void PPCRecompiler_visitAddressNoBlock(uint32 enterAddress) if (ppcRecompilerInstanceData->ppcRecompilerDirectJumpTable[enterAddress / 4] != PPCRecompiler_leaveRecompilerCode_unvisited) return; // try to acquire lock - if (!PPCRecompilerState.recompilerSpinlock.tryAcquire()) + if (!PPCRecompilerState.recompilerSpinlock.try_lock()) return; auto funcPtr = ppcRecompilerInstanceData->ppcRecompilerDirectJumpTable[enterAddress / 4]; if (funcPtr != PPCRecompiler_leaveRecompilerCode_unvisited) { // was visited since previous check - PPCRecompilerState.recompilerSpinlock.release(); + PPCRecompilerState.recompilerSpinlock.unlock(); return; } // add to recompilation queue and flag as visited PPCRecompilerState.targetQueue.emplace(enterAddress); ppcRecompilerInstanceData->ppcRecompilerDirectJumpTable[enterAddress / 4] = PPCRecompiler_leaveRecompilerCode_visited; - PPCRecompilerState.recompilerSpinlock.release(); + PPCRecompilerState.recompilerSpinlock.unlock(); } void PPCRecompiler_recompileIfUnvisited(uint32 enterAddress) @@ -193,13 +193,13 @@ PPCRecFunction_t* PPCRecompiler_recompileFunction(PPCFunctionBoundaryTracker::PP bool PPCRecompiler_makeRecompiledFunctionActive(uint32 initialEntryPoint, PPCFunctionBoundaryTracker::PPCRange_t& range, PPCRecFunction_t* ppcRecFunc, std::vector>& entryPoints) { // update jump table - PPCRecompilerState.recompilerSpinlock.acquire(); + PPCRecompilerState.recompilerSpinlock.lock(); // check if the initial entrypoint is still flagged for recompilation // its possible that the range has been invalidated during the time it took to translate the function if (ppcRecompilerInstanceData->ppcRecompilerDirectJumpTable[initialEntryPoint / 4] != PPCRecompiler_leaveRecompilerCode_visited) { - PPCRecompilerState.recompilerSpinlock.release(); + PPCRecompilerState.recompilerSpinlock.unlock(); return false; } @@ -221,7 +221,7 @@ bool PPCRecompiler_makeRecompiledFunctionActive(uint32 initialEntryPoint, PPCFun PPCRecompilerState.invalidationRanges.clear(); if (isInvalidated) { - PPCRecompilerState.recompilerSpinlock.release(); + PPCRecompilerState.recompilerSpinlock.unlock(); return false; } @@ -249,7 +249,7 @@ bool PPCRecompiler_makeRecompiledFunctionActive(uint32 initialEntryPoint, PPCFun { r.storedRange = rangeStore_ppcRanges.storeRange(ppcRecFunc, r.ppcAddress, r.ppcAddress + r.ppcSize); } - PPCRecompilerState.recompilerSpinlock.release(); + PPCRecompilerState.recompilerSpinlock.unlock(); return true; @@ -272,13 +272,13 @@ void PPCRecompiler_recompileAtAddress(uint32 address) // todo - use info from previously compiled ranges to determine full size of this function (and merge all the entryAddresses) // collect all currently known entry points for this range - PPCRecompilerState.recompilerSpinlock.acquire(); + PPCRecompilerState.recompilerSpinlock.lock(); std::set entryAddresses; entryAddresses.emplace(address); - PPCRecompilerState.recompilerSpinlock.release(); + PPCRecompilerState.recompilerSpinlock.unlock(); std::vector> functionEntryPoints; auto func = PPCRecompiler_recompileFunction(range, entryAddresses, functionEntryPoints); @@ -302,10 +302,10 @@ void PPCRecompiler_thread() // 3) if yes -> calculate size, gather all entry points, recompile and update jump table while (true) { - PPCRecompilerState.recompilerSpinlock.acquire(); + PPCRecompilerState.recompilerSpinlock.lock(); if (PPCRecompilerState.targetQueue.empty()) { - PPCRecompilerState.recompilerSpinlock.release(); + PPCRecompilerState.recompilerSpinlock.unlock(); break; } auto enterAddress = PPCRecompilerState.targetQueue.front(); @@ -315,10 +315,10 @@ void PPCRecompiler_thread() if (funcPtr != PPCRecompiler_leaveRecompilerCode_visited) { // only recompile functions if marked as visited - PPCRecompilerState.recompilerSpinlock.release(); + PPCRecompilerState.recompilerSpinlock.unlock(); continue; } - PPCRecompilerState.recompilerSpinlock.release(); + PPCRecompilerState.recompilerSpinlock.unlock(); PPCRecompiler_recompileAtAddress(enterAddress); } @@ -376,7 +376,7 @@ struct ppcRecompilerFuncRange_t bool PPCRecompiler_findFuncRanges(uint32 addr, ppcRecompilerFuncRange_t* rangesOut, size_t* countInOut) { - PPCRecompilerState.recompilerSpinlock.acquire(); + PPCRecompilerState.recompilerSpinlock.lock(); size_t countIn = *countInOut; size_t countOut = 0; @@ -392,7 +392,7 @@ bool PPCRecompiler_findFuncRanges(uint32 addr, ppcRecompilerFuncRange_t* rangesO countOut++; } ); - PPCRecompilerState.recompilerSpinlock.release(); + PPCRecompilerState.recompilerSpinlock.unlock(); *countInOut = countOut; if (countOut > countIn) return false; @@ -420,7 +420,7 @@ void PPCRecompiler_invalidateTableRange(uint32 offset, uint32 size) void PPCRecompiler_deleteFunction(PPCRecFunction_t* func) { // assumes PPCRecompilerState.recompilerSpinlock is already held - cemu_assert_debug(PPCRecompilerState.recompilerSpinlock.isHolding()); + cemu_assert_debug(PPCRecompilerState.recompilerSpinlock.is_locked()); for (auto& r : func->list_ranges) { PPCRecompiler_invalidateTableRange(r.ppcAddress, r.ppcSize); @@ -439,7 +439,7 @@ void PPCRecompiler_invalidateRange(uint32 startAddr, uint32 endAddr) return; cemu_assert_debug(endAddr >= startAddr); - PPCRecompilerState.recompilerSpinlock.acquire(); + PPCRecompilerState.recompilerSpinlock.lock(); uint32 rStart; uint32 rEnd; @@ -458,7 +458,7 @@ void PPCRecompiler_invalidateRange(uint32 startAddr, uint32 endAddr) PPCRecompiler_deleteFunction(rFunc); } - PPCRecompilerState.recompilerSpinlock.release(); + PPCRecompilerState.recompilerSpinlock.unlock(); } void PPCRecompiler_init() diff --git a/src/Cafe/HW/Latte/Core/FetchShader.cpp b/src/Cafe/HW/Latte/Core/FetchShader.cpp index c6756f4e..b4beba4e 100644 --- a/src/Cafe/HW/Latte/Core/FetchShader.cpp +++ b/src/Cafe/HW/Latte/Core/FetchShader.cpp @@ -516,16 +516,16 @@ FSpinlock s_spinlockFetchShaderCache; LatteFetchShader* LatteFetchShader::RegisterInCache(CacheHash fsHash) { - s_spinlockFetchShaderCache.acquire(); + s_spinlockFetchShaderCache.lock(); auto itr = s_fetchShaderByHash.find(fsHash); if (itr != s_fetchShaderByHash.end()) { LatteFetchShader* fs = itr->second; - s_spinlockFetchShaderCache.release(); + s_spinlockFetchShaderCache.unlock(); return fs; } s_fetchShaderByHash.emplace(fsHash, this); - s_spinlockFetchShaderCache.release(); + s_spinlockFetchShaderCache.unlock(); return nullptr; } @@ -533,11 +533,11 @@ void LatteFetchShader::UnregisterInCache() { if (!m_isRegistered) return; - s_spinlockFetchShaderCache.acquire(); + s_spinlockFetchShaderCache.lock(); auto itr = s_fetchShaderByHash.find(m_cacheHash); cemu_assert(itr == s_fetchShaderByHash.end()); s_fetchShaderByHash.erase(itr); - s_spinlockFetchShaderCache.release(); + s_spinlockFetchShaderCache.unlock(); } std::unordered_map LatteFetchShader::s_fetchShaderByHash; diff --git a/src/Cafe/HW/Latte/Core/LatteBufferCache.cpp b/src/Cafe/HW/Latte/Core/LatteBufferCache.cpp index 1e2c43b1..b0917895 100644 --- a/src/Cafe/HW/Latte/Core/LatteBufferCache.cpp +++ b/src/Cafe/HW/Latte/Core/LatteBufferCache.cpp @@ -1074,19 +1074,19 @@ void LatteBufferCache_notifyDCFlush(MPTR address, uint32 size) uint32 firstPage = address / CACHE_PAGE_SIZE; uint32 lastPage = (address + size - 1) / CACHE_PAGE_SIZE; - g_spinlockDCFlushQueue.acquire(); + g_spinlockDCFlushQueue.lock(); for (uint32 i = firstPage; i <= lastPage; i++) s_DCFlushQueue->Set(i); - g_spinlockDCFlushQueue.release(); + g_spinlockDCFlushQueue.unlock(); } void LatteBufferCache_processDCFlushQueue() { if (s_DCFlushQueue->Empty()) // quick check to avoid locking if there is no work to do return; - g_spinlockDCFlushQueue.acquire(); + g_spinlockDCFlushQueue.lock(); std::swap(s_DCFlushQueue, s_DCFlushQueueAlternate); - g_spinlockDCFlushQueue.release(); + g_spinlockDCFlushQueue.unlock(); s_DCFlushQueueAlternate->ForAllAndClear([](uint32 index) {LatteBufferCache_invalidatePage(index * CACHE_PAGE_SIZE); }); } diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/CachedFBOVk.h b/src/Cafe/HW/Latte/Renderer/Vulkan/CachedFBOVk.h index b83bd96c..4e6be012 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/CachedFBOVk.h +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/CachedFBOVk.h @@ -37,16 +37,16 @@ public: void TrackDependency(class PipelineInfo* pipelineInfo) { - s_spinlockDependency.acquire(); + s_spinlockDependency.lock(); m_usedByPipelines.emplace_back(pipelineInfo); - s_spinlockDependency.release(); + s_spinlockDependency.unlock(); } void RemoveDependency(class PipelineInfo* pipelineInfo) { - s_spinlockDependency.acquire(); + s_spinlockDependency.lock(); vectorRemoveByValue(m_usedByPipelines, pipelineInfo); - s_spinlockDependency.release(); + s_spinlockDependency.unlock(); } [[nodiscard]] const VkExtent2D& GetExtend() const { return m_extend;} diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h index 5be9ce1f..b1883c3d 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h @@ -37,16 +37,16 @@ public: void TrackDependency(class PipelineInfo* p) { - s_dependencyLock.acquire(); + s_dependencyLock.lock(); list_pipelineInfo.emplace_back(p); - s_dependencyLock.release(); + s_dependencyLock.unlock(); } void RemoveDependency(class PipelineInfo* p) { - s_dependencyLock.acquire(); + s_dependencyLock.lock(); vectorRemoveByValue(list_pipelineInfo, p); - s_dependencyLock.release(); + s_dependencyLock.unlock(); } void PreponeCompilation(bool isRenderThread) override; diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineStableCache.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineStableCache.cpp index 38f7c882..0d3ff771 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineStableCache.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineStableCache.cpp @@ -206,18 +206,18 @@ void VulkanPipelineStableCache::LoadPipelineFromCache(std::span fileData) // deserialize file LatteContextRegister* lcr = new LatteContextRegister(); - s_spinlockSharedInternal.acquire(); + s_spinlockSharedInternal.lock(); CachedPipeline* cachedPipeline = new CachedPipeline(); - s_spinlockSharedInternal.release(); + s_spinlockSharedInternal.unlock(); MemStreamReader streamReader(fileData.data(), fileData.size()); if (!DeserializePipeline(streamReader, *cachedPipeline)) { // failed to deserialize - s_spinlockSharedInternal.acquire(); + s_spinlockSharedInternal.lock(); delete lcr; delete cachedPipeline; - s_spinlockSharedInternal.release(); + s_spinlockSharedInternal.unlock(); return; } // restored register view from compacted state @@ -264,18 +264,18 @@ void VulkanPipelineStableCache::LoadPipelineFromCache(std::span fileData) } auto renderPass = __CreateTemporaryRenderPass(pixelShader, *lcr); // create pipeline info - m_pipelineIsCachedLock.acquire(); + m_pipelineIsCachedLock.lock(); PipelineInfo* pipelineInfo = new PipelineInfo(0, 0, vertexShader->compatibleFetchShader, vertexShader, pixelShader, geometryShader); - m_pipelineIsCachedLock.release(); + m_pipelineIsCachedLock.unlock(); // compile { PipelineCompiler pp; if (!pp.InitFromCurrentGPUState(pipelineInfo, *lcr, renderPass)) { - s_spinlockSharedInternal.acquire(); + s_spinlockSharedInternal.lock(); delete lcr; delete cachedPipeline; - s_spinlockSharedInternal.release(); + s_spinlockSharedInternal.unlock(); return; } pp.Compile(true, true, false); @@ -284,16 +284,16 @@ void VulkanPipelineStableCache::LoadPipelineFromCache(std::span fileData) // on success, calculate pipeline hash and flag as present in cache uint64 pipelineBaseHash = vertexShader->baseHash; uint64 pipelineStateHash = VulkanRenderer::draw_calculateGraphicsPipelineHash(vertexShader->compatibleFetchShader, vertexShader, geometryShader, pixelShader, renderPass, *lcr); - m_pipelineIsCachedLock.acquire(); + m_pipelineIsCachedLock.lock(); m_pipelineIsCached.emplace(pipelineBaseHash, pipelineStateHash); - m_pipelineIsCachedLock.release(); + m_pipelineIsCachedLock.unlock(); // clean up - s_spinlockSharedInternal.acquire(); + s_spinlockSharedInternal.lock(); delete pipelineInfo; delete lcr; delete cachedPipeline; VulkanRenderer::GetInstance()->releaseDestructibleObject(renderPass); - s_spinlockSharedInternal.release(); + s_spinlockSharedInternal.unlock(); } bool VulkanPipelineStableCache::HasPipelineCached(uint64 baseHash, uint64 pipelineStateHash) diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp index 5cbf7f94..35d81446 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp @@ -3447,14 +3447,14 @@ void VulkanRenderer::releaseDestructibleObject(VKRDestructibleObject* destructib return; } // otherwise put on queue - m_spinlockDestructionQueue.acquire(); + m_spinlockDestructionQueue.lock(); m_destructionQueue.emplace_back(destructibleObject); - m_spinlockDestructionQueue.release(); + m_spinlockDestructionQueue.unlock(); } void VulkanRenderer::ProcessDestructionQueue2() { - m_spinlockDestructionQueue.acquire(); + m_spinlockDestructionQueue.lock(); for (auto it = m_destructionQueue.begin(); it != m_destructionQueue.end();) { if ((*it)->canDestroy()) @@ -3465,7 +3465,7 @@ void VulkanRenderer::ProcessDestructionQueue2() } ++it; } - m_spinlockDestructionQueue.release(); + m_spinlockDestructionQueue.unlock(); } VkDescriptorSetInfo::~VkDescriptorSetInfo() @@ -4010,9 +4010,9 @@ void VulkanRenderer::AppendOverlayDebugInfo() ImGui::Text("ImageView %u", performanceMonitor.vk.numImageViews.get()); ImGui::Text("RenderPass %u", performanceMonitor.vk.numRenderPass.get()); ImGui::Text("Framebuffer %u", performanceMonitor.vk.numFramebuffer.get()); - m_spinlockDestructionQueue.acquire(); + m_spinlockDestructionQueue.lock(); ImGui::Text("DestructionQ %u", (unsigned int)m_destructionQueue.size()); - m_spinlockDestructionQueue.release(); + m_spinlockDestructionQueue.unlock(); ImGui::Text("BeginRP/f %u", performanceMonitor.vk.numBeginRenderpassPerFrame.get()); diff --git a/src/Cafe/IOSU/kernel/iosu_kernel.cpp b/src/Cafe/IOSU/kernel/iosu_kernel.cpp index 1a642028..680170bc 100644 --- a/src/Cafe/IOSU/kernel/iosu_kernel.cpp +++ b/src/Cafe/IOSU/kernel/iosu_kernel.cpp @@ -234,38 +234,38 @@ namespace iosu void _IPCInitDispatchablePool() { - sIPCDispatchableCommandPoolLock.acquire(); + sIPCDispatchableCommandPoolLock.lock(); while (!sIPCFreeDispatchableCommands.empty()) sIPCFreeDispatchableCommands.pop(); for (size_t i = 0; i < sIPCDispatchableCommandPool.GetCount(); i++) sIPCFreeDispatchableCommands.push(sIPCDispatchableCommandPool.GetPtr()+i); - sIPCDispatchableCommandPoolLock.release(); + sIPCDispatchableCommandPoolLock.unlock(); } IOSDispatchableCommand* _IPCAllocateDispatchableCommand() { - sIPCDispatchableCommandPoolLock.acquire(); + sIPCDispatchableCommandPoolLock.lock(); if (sIPCFreeDispatchableCommands.empty()) { cemuLog_log(LogType::Force, "IOS: Exhausted pool of dispatchable commands"); - sIPCDispatchableCommandPoolLock.release(); + sIPCDispatchableCommandPoolLock.unlock(); return nullptr; } IOSDispatchableCommand* cmd = sIPCFreeDispatchableCommands.front(); sIPCFreeDispatchableCommands.pop(); cemu_assert_debug(!cmd->isAllocated); cmd->isAllocated = true; - sIPCDispatchableCommandPoolLock.release(); + sIPCDispatchableCommandPoolLock.unlock(); return cmd; } void _IPCReleaseDispatchableCommand(IOSDispatchableCommand* cmd) { - sIPCDispatchableCommandPoolLock.acquire(); + sIPCDispatchableCommandPoolLock.lock(); cemu_assert_debug(cmd->isAllocated); cmd->isAllocated = false; sIPCFreeDispatchableCommands.push(cmd); - sIPCDispatchableCommandPoolLock.release(); + sIPCDispatchableCommandPoolLock.unlock(); } static constexpr size_t MAX_NUM_ACTIVE_DEV_HANDLES = 96; // per process diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Callbacks.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Callbacks.cpp index 403bec61..aef7e5aa 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_Callbacks.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_Callbacks.cpp @@ -8,27 +8,27 @@ struct CoreinitAsyncCallback static void queue(MPTR functionMPTR, uint32 numParameters, uint32 r3, uint32 r4, uint32 r5, uint32 r6, uint32 r7, uint32 r8, uint32 r9, uint32 r10) { - s_asyncCallbackSpinlock.acquire(); + s_asyncCallbackSpinlock.lock(); s_asyncCallbackQueue.emplace_back(allocateAndInitFromPool(functionMPTR, numParameters, r3, r4, r5, r6, r7, r8, r9, r10)); - s_asyncCallbackSpinlock.release(); + s_asyncCallbackSpinlock.unlock(); } static void callNextFromQueue() { - s_asyncCallbackSpinlock.acquire(); + s_asyncCallbackSpinlock.lock(); if (s_asyncCallbackQueue.empty()) { cemuLog_log(LogType::Force, "AsyncCallbackQueue is empty. Unexpected behavior"); - s_asyncCallbackSpinlock.release(); + s_asyncCallbackSpinlock.unlock(); return; } CoreinitAsyncCallback* cb = s_asyncCallbackQueue[0]; s_asyncCallbackQueue.erase(s_asyncCallbackQueue.begin()); - s_asyncCallbackSpinlock.release(); + s_asyncCallbackSpinlock.unlock(); cb->doCall(); - s_asyncCallbackSpinlock.acquire(); + s_asyncCallbackSpinlock.lock(); releaseToPool(cb); - s_asyncCallbackSpinlock.release(); + s_asyncCallbackSpinlock.unlock(); } private: @@ -39,7 +39,7 @@ private: static CoreinitAsyncCallback* allocateAndInitFromPool(MPTR functionMPTR, uint32 numParameters, uint32 r3, uint32 r4, uint32 r5, uint32 r6, uint32 r7, uint32 r8, uint32 r9, uint32 r10) { - cemu_assert_debug(s_asyncCallbackSpinlock.isHolding()); + cemu_assert_debug(s_asyncCallbackSpinlock.is_locked()); if (s_asyncCallbackPool.empty()) { CoreinitAsyncCallback* cb = new CoreinitAsyncCallback(functionMPTR, numParameters, r3, r4, r5, r6, r7, r8, r9, r10); @@ -54,7 +54,7 @@ private: static void releaseToPool(CoreinitAsyncCallback* cb) { - cemu_assert_debug(s_asyncCallbackSpinlock.isHolding()); + cemu_assert_debug(s_asyncCallbackSpinlock.is_locked()); s_asyncCallbackPool.emplace_back(cb); } diff --git a/src/Cafe/OS/libs/coreinit/coreinit_MPQueue.cpp b/src/Cafe/OS/libs/coreinit/coreinit_MPQueue.cpp index 8fc5a935..1816ef24 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_MPQueue.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_MPQueue.cpp @@ -6,8 +6,8 @@ // titles that utilize MP task queue: Yoshi's Woolly World, Fast Racing Neo, Tokyo Mirage Sessions, Mii Maker -#define AcquireMPQLock() s_workaroundSpinlock.acquire() -#define ReleaseMPQLock() s_workaroundSpinlock.release() +#define AcquireMPQLock() s_workaroundSpinlock.lock() +#define ReleaseMPQLock() s_workaroundSpinlock.unlock() namespace coreinit { @@ -35,7 +35,7 @@ namespace coreinit void MPInitTask(MPTask* task, void* func, void* data, uint32 size) { - s_workaroundSpinlock.acquire(); + s_workaroundSpinlock.lock(); task->thisptr = task; task->coreIndex = PPC_CORE_COUNT; @@ -48,7 +48,7 @@ namespace coreinit task->userdata = nullptr; task->runtime = 0; - s_workaroundSpinlock.release(); + s_workaroundSpinlock.unlock(); } bool MPTermTask(MPTask* task) diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Synchronization.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Synchronization.cpp index 84f7c5cf..bdcc531d 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_Synchronization.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_Synchronization.cpp @@ -465,12 +465,12 @@ namespace coreinit void _OSFastMutex_AcquireContention(OSFastMutex* fastMutex) { - g_fastMutexSpinlock.acquire(); + g_fastMutexSpinlock.lock(); } void _OSFastMutex_ReleaseContention(OSFastMutex* fastMutex) { - g_fastMutexSpinlock.release(); + g_fastMutexSpinlock.unlock(); } void OSFastMutex_LockInternal(OSFastMutex* fastMutex) diff --git a/src/Cafe/OS/libs/snd_core/ax_ist.cpp b/src/Cafe/OS/libs/snd_core/ax_ist.cpp index 26f975af..528a8302 100644 --- a/src/Cafe/OS/libs/snd_core/ax_ist.cpp +++ b/src/Cafe/OS/libs/snd_core/ax_ist.cpp @@ -778,7 +778,7 @@ namespace snd_core void AXIst_SyncVPB(AXVPBInternal_t** lastProcessedDSPShadowCopy, AXVPBInternal_t** lastProcessedPPCShadowCopy) { - __AXVoiceListSpinlock.acquire(); + __AXVoiceListSpinlock.lock(); AXVPBInternal_t* previousInternalDSP = nullptr; AXVPBInternal_t* previousInternalPPC = nullptr; @@ -869,7 +869,7 @@ namespace snd_core else *lastProcessedPPCShadowCopy = nullptr; } - __AXVoiceListSpinlock.release(); + __AXVoiceListSpinlock.unlock(); } void AXIst_HandleFrameCallbacks() diff --git a/src/Cafe/OS/libs/snd_core/ax_voice.cpp b/src/Cafe/OS/libs/snd_core/ax_voice.cpp index 746f04d3..6a599c8b 100644 --- a/src/Cafe/OS/libs/snd_core/ax_voice.cpp +++ b/src/Cafe/OS/libs/snd_core/ax_voice.cpp @@ -393,7 +393,7 @@ namespace snd_core AXVPB* AXAcquireVoiceEx(uint32 priority, MPTR callbackEx, MPTR userParam) { cemu_assert(priority != AX_PRIORITY_FREE && priority < AX_PRIORITY_MAX); - __AXVoiceListSpinlock.acquire(); + __AXVoiceListSpinlock.lock(); AXVPB* vpb = AXVoiceList_GetFreeVoice(); if (vpb != nullptr) { @@ -410,7 +410,7 @@ namespace snd_core if (droppedVoice == nullptr) { // no voice available - __AXVoiceListSpinlock.release(); + __AXVoiceListSpinlock.unlock(); return nullptr; } vpb->userParam = userParam; @@ -418,18 +418,18 @@ namespace snd_core vpb->callbackEx = callbackEx; AXVPB_SetVoiceDefault(vpb); } - __AXVoiceListSpinlock.release(); + __AXVoiceListSpinlock.unlock(); return vpb; } void AXFreeVoice(AXVPB* vpb) { cemu_assert(vpb != nullptr); - __AXVoiceListSpinlock.acquire(); + __AXVoiceListSpinlock.lock(); if (vpb->priority == (uint32be)AX_PRIORITY_FREE) { forceLog_printf("AXFreeVoice() called on free voice\n"); - __AXVoiceListSpinlock.release(); + __AXVoiceListSpinlock.unlock(); return; } AXVoiceProtection_Release(vpb); @@ -442,7 +442,7 @@ namespace snd_core vpb->callback = MPTR_NULL; vpb->callbackEx = MPTR_NULL; AXVoiceList_AddFreeVoice(vpb); - __AXVoiceListSpinlock.release(); + __AXVoiceListSpinlock.unlock(); } void AXVPBInit() diff --git a/src/gui/guiWrapper.h b/src/gui/guiWrapper.h index ce041efb..4f46f8b4 100644 --- a/src/gui/guiWrapper.h +++ b/src/gui/guiWrapper.h @@ -45,7 +45,8 @@ struct WindowInfo { const std::lock_guard lock(keycode_mutex); m_keydown[keycode] = state; - }; + } + bool get_keystate(uint32 keycode) { const std::lock_guard lock(keycode_mutex); @@ -54,25 +55,20 @@ struct WindowInfo return false; return result->second; } - void get_keystates(std::unordered_map& buttons_out) - { - const std::lock_guard lock(keycode_mutex); - for (auto&& button : m_keydown) - { - buttons_out[button.first] = button.second; - } - } + void set_keystatesdown() { const std::lock_guard lock(keycode_mutex); std::for_each(m_keydown.begin(), m_keydown.end(), [](std::pair& el){ el.second = false; }); } + template void iter_keystates(fn f) { const std::lock_guard lock(keycode_mutex); std::for_each(m_keydown.cbegin(), m_keydown.cend(), f); } + WindowHandleInfo window_main; WindowHandleInfo window_pad; diff --git a/src/gui/input/InputSettings2.cpp b/src/gui/input/InputSettings2.cpp index 095aa52a..7757a2ae 100644 --- a/src/gui/input/InputSettings2.cpp +++ b/src/gui/input/InputSettings2.cpp @@ -111,7 +111,7 @@ InputSettings2::InputSettings2(wxWindow* parent) Bind(wxEVT_TIMER, &InputSettings2::on_timer, this); m_timer = new wxTimer(this); - m_timer->Start(100); + m_timer->Start(25); m_controller_changed = EventService::instance().connect(&InputSettings2::on_controller_changed, this); } diff --git a/src/gui/input/panels/InputPanel.cpp b/src/gui/input/panels/InputPanel.cpp index b01157c8..984b46d7 100644 --- a/src/gui/input/panels/InputPanel.cpp +++ b/src/gui/input/panels/InputPanel.cpp @@ -41,77 +41,69 @@ void InputPanel::on_timer(const EmulatedControllerPtr& emulated_controller, cons } static bool s_was_idle = true; - if (!std::any_of(state.buttons.begin(), state.buttons.end(), [](auto el){ return el.second; })) { + if (state.buttons.IsIdle()) + { s_was_idle = true; return; } - if (!s_was_idle) { + if (!s_was_idle) + { return; } - auto get_button_state = [&](uint32 key_id) - { - auto result = state.buttons.find(key_id); - if (result == state.buttons.end()) - return false; - return result->second; - }; s_was_idle = false; - for(auto && button : state.buttons) + for(const auto& id : state.buttons.GetButtonList()) { - if (button.second) + if (controller->has_axis()) { - auto id=button.first; - if (controller->has_axis()) { - // test if one axis direction is pressed more than the other - if ((id == kAxisXP || id == kAxisXN) && (get_button_state(kAxisYP) || get_button_state(kAxisYN))) - { - if (std::abs(state.axis.y) > std::abs(state.axis.x)) - continue; - } - else if ((id == kAxisYP || id == kAxisYN) && (get_button_state(kAxisXP) || get_button_state(kAxisXN))) - { - if (std::abs(state.axis.x) > std::abs(state.axis.y)) - continue; - } - else if ((id == kRotationXP || id == kRotationXN) && (get_button_state(kRotationYP) || get_button_state(kRotationYN))) - { - if (std::abs(state.rotation.y) > std::abs(state.rotation.x)) - continue; - } - else if ((id == kRotationYP || id == kRotationYN) && (get_button_state(kRotationXP) || get_button_state(kRotationXN))) - { - if (std::abs(state.rotation.x) > std::abs(state.rotation.y)) - continue; - } - else if ((id == kTriggerXP || id == kTriggerXN) && (get_button_state(kTriggerYP) || get_button_state(kTriggerYN))) - { - if (std::abs(state.trigger.y) > std::abs(state.trigger.x)) - continue; - } - else if ((id == kTriggerYP || id == kTriggerYN) && (get_button_state(kTriggerXP) || get_button_state(kTriggerXN))) - { - if (std::abs(state.trigger.x) > std::abs(state.trigger.y)) - continue; - } - - // ignore too low button values on configuration - if (id >= kButtonAxisStart) - { - if (controller->get_axis_value(id) < 0.33f) { - forceLogDebug_printf("skipping since value too low %f", controller->get_axis_value(id)); - s_was_idle = true; - return; - } - } + // test if one axis direction is pressed more than the other + if ((id == kAxisXP || id == kAxisXN) && (state.buttons.GetButtonState(kAxisYP) || state.buttons.GetButtonState(kAxisYN))) + { + if (std::abs(state.axis.y) > std::abs(state.axis.x)) + continue; + } + else if ((id == kAxisYP || id == kAxisYN) && (state.buttons.GetButtonState(kAxisXP) || state.buttons.GetButtonState(kAxisXN))) + { + if (std::abs(state.axis.x) > std::abs(state.axis.y)) + continue; + } + else if ((id == kRotationXP || id == kRotationXN) && (state.buttons.GetButtonState(kRotationYP) || state.buttons.GetButtonState(kRotationYN))) + { + if (std::abs(state.rotation.y) > std::abs(state.rotation.x)) + continue; + } + else if ((id == kRotationYP || id == kRotationYN) && (state.buttons.GetButtonState(kRotationXP) || state.buttons.GetButtonState(kRotationXN))) + { + if (std::abs(state.rotation.x) > std::abs(state.rotation.y)) + continue; + } + else if ((id == kTriggerXP || id == kTriggerXN) && (state.buttons.GetButtonState(kTriggerYP) || state.buttons.GetButtonState(kTriggerYN))) + { + if (std::abs(state.trigger.y) > std::abs(state.trigger.x)) + continue; + } + else if ((id == kTriggerYP || id == kTriggerYN) && (state.buttons.GetButtonState(kTriggerXP) || state.buttons.GetButtonState(kTriggerXN))) + { + if (std::abs(state.trigger.x) > std::abs(state.trigger.y)) + continue; } - emulated_controller->set_mapping(mapping, controller, id); - element->SetValue(controller->get_button_name(id)); - element->SetBackgroundColour(kKeyColourNormalMode); - m_color_backup[element->GetId()] = kKeyColourNormalMode; - break; + // ignore too low button values on configuration + if (id >= kButtonAxisStart) + { + if (controller->get_axis_value(id) < 0.33f) { + forceLogDebug_printf("skipping since value too low %f", controller->get_axis_value(id)); + s_was_idle = true; + return; + } + } } + + emulated_controller->set_mapping(mapping, controller, id); + element->SetValue(controller->get_button_name(id)); + element->SetBackgroundColour(kKeyColourNormalMode); + m_color_backup[element->GetId()] = kKeyColourNormalMode; + break; } if (const auto sibling = get_next_sibling(element)) diff --git a/src/input/api/Controller.cpp b/src/input/api/Controller.cpp index a75cdf57..b7831def 100644 --- a/src/input/api/Controller.cpp +++ b/src/input/api/Controller.cpp @@ -15,10 +15,7 @@ const ControllerState& ControllerBase::update_state() ControllerState result = raw_state(); // ignore default buttons - for (auto&& el : m_default_state.buttons) - { - result.buttons[el.first] = result.buttons[el.first] && !el.second; - } + result.buttons.UnsetButtons(m_default_state.buttons); // apply deadzone and range and ignore default axis values apply_axis_setting(result.axis, m_default_state.axis, m_settings.axis); apply_axis_setting(result.rotation, m_default_state.rotation, m_settings.rotation); @@ -26,22 +23,22 @@ const ControllerState& ControllerBase::update_state() #define APPLY_AXIS_BUTTON(_axis_, _flag_) \ if (result._axis_.x < -ControllerState::kAxisThreshold) \ - result.buttons[(_flag_) + (kAxisXN - kAxisXP)]=true; \ + result.buttons.SetButtonState((_flag_) + (kAxisXN - kAxisXP), true); \ else if (result._axis_.x > ControllerState::kAxisThreshold) \ - result.buttons[(_flag_)]=true; \ + result.buttons.SetButtonState((_flag_), true); \ if (result._axis_.y < -ControllerState::kAxisThreshold) \ - result.buttons[(_flag_) + 1 + (kAxisXN - kAxisXP)]=true; \ + result.buttons.SetButtonState((_flag_) + 1 + (kAxisXN - kAxisXP), true); \ else if (result._axis_.y > ControllerState::kAxisThreshold) \ - result.buttons[(_flag_) + 1]=true; + result.buttons.SetButtonState((_flag_) + 1, true); if (result.axis.x < -ControllerState::kAxisThreshold) - result.buttons[(kAxisXP) + (kAxisXN - kAxisXP)]=true; + result.buttons.SetButtonState((kAxisXP) + (kAxisXN - kAxisXP), true); else if (result.axis.x > ControllerState::kAxisThreshold) - result.buttons[(kAxisXP)]=true; + result.buttons.SetButtonState((kAxisXP), true); if (result.axis.y < -ControllerState::kAxisThreshold) - result.buttons[(kAxisXP) + 1 + (kAxisXN - kAxisXP)]=true; + result.buttons.SetButtonState((kAxisXP) + 1 + (kAxisXN - kAxisXP), true); else if (result.axis.y > ControllerState::kAxisThreshold) - result.buttons[(kAxisXP) + 1]=true; + result.buttons.SetButtonState((kAxisXP) + 1, true); APPLY_AXIS_BUTTON(rotation, kRotationXP); APPLY_AXIS_BUTTON(trigger, kTriggerXP); @@ -129,8 +126,7 @@ bool ControllerBase::operator==(const ControllerBase& c) const float ControllerBase::get_axis_value(uint64 button) const { - auto buttonState=m_last_state.buttons.find(button); - if (buttonState!=m_last_state.buttons.end() && buttonState->second) + if (m_last_state.buttons.GetButtonState(button)) { if (button <= kButtonNoneAxisMAX || !has_axis()) return 1.0f; diff --git a/src/input/api/ControllerState.h b/src/input/api/ControllerState.h index a8ff6628..3e6149ab 100644 --- a/src/input/api/ControllerState.h +++ b/src/input/api/ControllerState.h @@ -1,6 +1,115 @@ #pragma once #include +#include "util/helpers/fspinlock.h" + +// helper class for storing and managing button press states in a thread-safe manner +struct ControllerButtonState +{ + ControllerButtonState() = default; + ControllerButtonState(const ControllerButtonState& other) + { + this->m_pressedButtons = other.m_pressedButtons; + } + + ControllerButtonState(ControllerButtonState&& other) + { + this->m_pressedButtons = std::move(other.m_pressedButtons); + } + + void SetButtonState(uint32 buttonId, bool isPressed) + { + std::lock_guard _l(this->m_spinlock); + if (isPressed) + { + if (std::find(m_pressedButtons.cbegin(), m_pressedButtons.cend(), buttonId) != m_pressedButtons.end()) + return; + m_pressedButtons.emplace_back(buttonId); + } + else + { + std::erase(m_pressedButtons, buttonId); + } + } + + // set multiple buttons at once within a single lock interval + void SetPressedButtons(std::span buttonList) + { + std::lock_guard _l(this->m_spinlock); + for (auto& buttonId : buttonList) + { + if (std::find(m_pressedButtons.cbegin(), m_pressedButtons.cend(), buttonId) == m_pressedButtons.end()) + m_pressedButtons.emplace_back(buttonId); + } + } + + // returns true if pressed + bool GetButtonState(uint32 buttonId) const + { + std::lock_guard _l(this->m_spinlock); + bool r = std::find(m_pressedButtons.cbegin(), m_pressedButtons.cend(), buttonId) != m_pressedButtons.cend(); + return r; + } + + // remove pressed state for all pressed buttons in buttonsToUnset + void UnsetButtons(const ControllerButtonState& buttonsToUnset) + { + std::scoped_lock _l(this->m_spinlock, buttonsToUnset.m_spinlock); + for (auto it = m_pressedButtons.begin(); it != m_pressedButtons.end();) + { + if (std::find(buttonsToUnset.m_pressedButtons.cbegin(), buttonsToUnset.m_pressedButtons.cend(), *it) == buttonsToUnset.m_pressedButtons.cend()) + { + ++it; + continue; + } + it = m_pressedButtons.erase(it); + } + } + + // returns true if no buttons are pressed + bool IsIdle() const + { + std::lock_guard _l(this->m_spinlock); + const bool r = m_pressedButtons.empty(); + return r; + } + + std::vector GetButtonList() const + { + std::lock_guard _l(this->m_spinlock); + std::vector copy = m_pressedButtons; + return copy; + } + + bool operator==(const ControllerButtonState& other) const + { + std::scoped_lock _l(this->m_spinlock, other.m_spinlock); + auto& otherButtons = other.m_pressedButtons; + if (m_pressedButtons.size() != otherButtons.size()) + { + return false; + } + for (auto& buttonId : m_pressedButtons) + { + if (std::find(otherButtons.cbegin(), otherButtons.cend(), buttonId) == otherButtons.cend()) + { + return false; + } + } + return true; + } + + ControllerButtonState& operator=(ControllerButtonState&& other) + { + cemu_assert_debug(!other.m_spinlock.is_locked()); + this->m_pressedButtons = std::move(other.m_pressedButtons); + return *this; + } + +private: + std::vector m_pressedButtons; // since only very few buttons are pressed at a time, using a vector with linear scan is more efficient than a set/map + mutable FSpinlock m_spinlock; +}; struct ControllerState { @@ -17,7 +126,7 @@ struct ControllerState glm::vec2 rotation{ }; glm::vec2 trigger{ }; - std::unordered_map buttons{}; + ControllerButtonState buttons{}; uint64 last_state = 0; diff --git a/src/input/api/DSU/DSUController.cpp b/src/input/api/DSU/DSUController.cpp index c04c8453..f134440c 100644 --- a/src/input/api/DSU/DSUController.cpp +++ b/src/input/api/DSU/DSUController.cpp @@ -137,7 +137,7 @@ ControllerState DSUController::raw_state() { if (HAS_BIT(state.data.state1, i)) { - result.buttons[bitindex]=true; + result.buttons.SetButtonState(bitindex, true); } } @@ -145,12 +145,12 @@ ControllerState DSUController::raw_state() { if (HAS_BIT(state.data.state2, i)) { - result.buttons[bitindex]=true; + result.buttons.SetButtonState(bitindex, true); } } if (state.data.touch) - result.buttons[kButton16]=true; + result.buttons.SetButtonState(kButton16, true); result.axis.x = (float)state.data.lx / std::numeric_limits::max(); result.axis.x = (result.axis.x * 2.0f) - 1.0f; diff --git a/src/input/api/DirectInput/DirectInputController.cpp b/src/input/api/DirectInput/DirectInputController.cpp index 87bd3685..dbb7c80c 100644 --- a/src/input/api/DirectInput/DirectInputController.cpp +++ b/src/input/api/DirectInput/DirectInputController.cpp @@ -245,7 +245,6 @@ ControllerState DirectInputController::raw_state() ControllerState result{}; if (!is_connected()) return result; - HRESULT hr = m_device->Poll(); if (FAILED(hr)) { @@ -277,9 +276,7 @@ ControllerState DirectInputController::raw_state() for (size_t i = 0; i < std::size(state.rgbButtons); ++i) { if (HAS_BIT(state.rgbButtons[i], 7)) - { - result.buttons[i]=true; - } + result.buttons.SetButtonState(i, true); } // axis @@ -316,19 +313,19 @@ ControllerState DirectInputController::raw_state() { switch (pov) { - case 0: result.buttons[kButtonUp]=true; + case 0: result.buttons.SetButtonState(kButtonUp, true); break; - case 4500: result.buttons[kButtonUp]=true; // up + right - case 9000: result.buttons[kButtonRight]=true; + case 4500: result.buttons.SetButtonState(kButtonUp, true); // up + right + case 9000: result.buttons.SetButtonState(kButtonRight, true); break; - case 13500: result.buttons[kButtonRight] = true; // right + down - case 18000: result.buttons[kButtonDown] = true; + case 13500: result.buttons.SetButtonState(kButtonRight, true); // right + down + case 18000: result.buttons.SetButtonState(kButtonDown, true); break; - case 22500: result.buttons[kButtonDown] = true; // down + left - case 27000: result.buttons[kButtonLeft] = true; + case 22500: result.buttons.SetButtonState(kButtonDown, true); // down + left + case 27000: result.buttons.SetButtonState(kButtonLeft, true); break; - case 31500: result.buttons[kButtonLeft] = true; // left + up - result.buttons[kButtonUp] = true; // left + up + case 31500: result.buttons.SetButtonState(kButtonLeft, true); // left + up + result.buttons.SetButtonState(kButtonUp, true); // left + up break; } } diff --git a/src/input/api/Keyboard/KeyboardController.cpp b/src/input/api/Keyboard/KeyboardController.cpp index 0d41fe1a..9cd31b4b 100644 --- a/src/input/api/Keyboard/KeyboardController.cpp +++ b/src/input/api/Keyboard/KeyboardController.cpp @@ -1,5 +1,6 @@ -#include "input/api/Keyboard/KeyboardController.h" +#include +#include "input/api/Keyboard/KeyboardController.h" #include "gui/guiWrapper.h" KeyboardController::KeyboardController() @@ -51,7 +52,9 @@ ControllerState KeyboardController::raw_state() ControllerState result{}; if (g_window_info.app_active) { - g_window_info.get_keystates(result.buttons); + boost::container::small_vector pressedKeys; + g_window_info.iter_keystates([&pressedKeys](const std::pair& keyState) { if (keyState.second) pressedKeys.emplace_back(keyState.first); }); + result.buttons.SetPressedButtons(pressedKeys); } return result; } diff --git a/src/input/api/SDL/SDLController.cpp b/src/input/api/SDL/SDLController.cpp index 63f7f4d3..a3e7eece 100644 --- a/src/input/api/SDL/SDLController.cpp +++ b/src/input/api/SDL/SDLController.cpp @@ -146,9 +146,7 @@ ControllerState SDLController::raw_state() for (int i = 0; i < SDL_CONTROLLER_BUTTON_MAX; ++i) { if (m_buttons[i] && SDL_GameControllerGetButton(m_controller, (SDL_GameControllerButton)i)) - { - result.buttons[i]=true; - } + result.buttons.SetButtonState(i, true); } if (m_axis[SDL_CONTROLLER_AXIS_LEFTX]) diff --git a/src/input/api/Wiimote/NativeWiimoteController.cpp b/src/input/api/Wiimote/NativeWiimoteController.cpp index c5059f7c..3f9e82a5 100644 --- a/src/input/api/Wiimote/NativeWiimoteController.cpp +++ b/src/input/api/Wiimote/NativeWiimoteController.cpp @@ -207,16 +207,16 @@ ControllerState NativeWiimoteController::raw_state() const auto state = m_provider->get_state(m_index); for (int i = 0; i < std::numeric_limits::digits; i++) - result.buttons[i] = state.buttons & (1<(state.m_extension)) { const auto nunchuck = std::get(state.m_extension); if (nunchuck.c) - result.buttons[kWiimoteButton_C]=true; + result.buttons.SetButtonState(kWiimoteButton_C, true); if (nunchuck.z) - result.buttons[kWiimoteButton_Z]=true; + result.buttons.SetButtonState(kWiimoteButton_Z, true); result.axis = nunchuck.axis; } @@ -225,8 +225,11 @@ ControllerState NativeWiimoteController::raw_state() const auto classic = std::get(state.m_extension); uint64 buttons = (uint64)classic.buttons << kHighestWiimote; for (int i = 0; i < std::numeric_limits::digits; i++) - result.buttons[i] = result.buttons[i] || (buttons & (1 << i)); - + { + // OR with base buttons + if((buttons & (1 << i))) + result.buttons.SetButtonState(i, true); + } result.axis = classic.left_axis; result.rotation = classic.right_axis; result.trigger = classic.trigger; diff --git a/src/input/api/XInput/XInputController.cpp b/src/input/api/XInput/XInputController.cpp index e2be29b6..c3ab67cf 100644 --- a/src/input/api/XInput/XInputController.cpp +++ b/src/input/api/XInput/XInputController.cpp @@ -121,7 +121,7 @@ ControllerState XInputController::raw_state() // Buttons for(int i=0;i::digits;i++) - result.buttons[i] = state.Gamepad.wButtons & (1< 0) result.axis.x = (float)state.Gamepad.sThumbLX / std::numeric_limits::max(); diff --git a/src/input/emulated/EmulatedController.cpp b/src/input/emulated/EmulatedController.cpp index 0028db58..b7a4743c 100644 --- a/src/input/emulated/EmulatedController.cpp +++ b/src/input/emulated/EmulatedController.cpp @@ -279,13 +279,9 @@ bool EmulatedController::is_mapping_down(uint64 mapping) const const auto it = m_mappings.find(mapping); if (it != m_mappings.cend()) { - if (const auto controller = it->second.controller.lock()) { - auto& buttons=controller->get_state().buttons; - auto buttonState=buttons.find(it->second.button); - return buttonState!=buttons.end() && buttonState->second; - } + if (const auto controller = it->second.controller.lock()) + return controller->get_state().buttons.GetButtonState(it->second.button); } - return false; } diff --git a/src/util/helpers/fspinlock.h b/src/util/helpers/fspinlock.h index 04f761e7..4fa642f4 100644 --- a/src/util/helpers/fspinlock.h +++ b/src/util/helpers/fspinlock.h @@ -7,32 +7,33 @@ class FSpinlock { public: - void acquire() + bool is_locked() const { - while( true ) + return m_lockBool.load(std::memory_order_relaxed); + } + + // implement BasicLockable and Lockable + void lock() const + { + while (true) { - if (!m_lockBool.exchange(true, std::memory_order_acquire)) + if (!m_lockBool.exchange(true, std::memory_order_acquire)) break; while (m_lockBool.load(std::memory_order_relaxed)) _mm_pause(); } } - bool tryAcquire() + bool try_lock() const { return !m_lockBool.exchange(true, std::memory_order_acquire); } - void release() + void unlock() const { m_lockBool.store(false, std::memory_order_release); } - bool isHolding() const - { - return m_lockBool.load(std::memory_order_relaxed); - } - private: - std::atomic m_lockBool = false; + mutable std::atomic m_lockBool = false; }; \ No newline at end of file From 8f674933d2b507ce91c17b69fef2c38c6f1fbcaf Mon Sep 17 00:00:00 2001 From: emiyl Date: Sun, 23 Oct 2022 15:58:28 +0100 Subject: [PATCH 017/589] Create Cemu .app bundle for macOS (#364) --- .github/workflows/build.yml | 17 +++++++-- .../workflows/deploy_experimental_release.yml | 8 +--- .github/workflows/deploy_stable_release.yml | 8 +--- CMakeLists.txt | 1 + src/CMakeLists.txt | 29 +++++++++++++- src/gui/CemuApp.cpp | 3 ++ src/resource/MacOSXBundleInfo.plist.in | 36 ++++++++++++++++++ src/resource/cemu.icns | Bin 0 -> 817145 bytes 8 files changed, 84 insertions(+), 18 deletions(-) create mode 100644 src/resource/MacOSXBundleInfo.plist.in create mode 100644 src/resource/cemu.icns diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ac010c8f..5fc56aec 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -162,6 +162,8 @@ jobs: with: name: cemu-bin-windows-x64 path: ./bin/Cemu.exe + + build-macos: runs-on: macos-12 steps: @@ -213,7 +215,7 @@ jobs: run: | mkdir build cd build - cmake .. ${{ env.BUILD_FLAGS }} -DCMAKE_BUILD_TYPE=${{ env.BUILD_MODE }} -DCMAKE_C_COMPILER=/usr/local/opt/llvm@14/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@14/bin/clang++ -G Ninja + cmake .. ${{ env.BUILD_FLAGS }} -DCMAKE_BUILD_TYPE=${{ env.BUILD_MODE }} -DPORTABLE=OFF -DMACOS_BUNDLE=ON -DCMAKE_C_COMPILER=/usr/local/opt/llvm@14/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@14/bin/clang++ -G Ninja - name: "Build Cemu" run: | @@ -221,11 +223,20 @@ jobs: - name: Prepare artifact if: ${{ inputs.deploymode == 'release' }} - run: chmod a+x bin/Cemu_release && mv bin/Cemu_release bin/Cemu + run: | + mkdir bin/Cemu_app + mv bin/Cemu_release.app bin/Cemu_app/Cemu.app + mv bin/Cemu_app/Cemu.app/Contents/MacOS/Cemu_release bin/Cemu_app/Cemu.app/Contents/MacOS/Cemu + sed -i '' 's/Cemu_release/Cemu/g' bin/Cemu_app/Cemu.app/Contents/Info.plist + chmod a+x bin/Cemu_app/Cemu.app/Contents/MacOS/Cemu + ln -s /Applications bin/Cemu_app/Applications + hdiutil create ./bin/tmp.dmg -ov -volname "Cemu" -fs HFS+ -srcfolder "./bin/Cemu_app" + hdiutil convert ./bin/tmp.dmg -format UDZO -o bin/Cemu.dmg + rm bin/tmp.dmg - name: Upload artifact uses: actions/upload-artifact@v3 if: ${{ inputs.deploymode == 'release' }} with: name: cemu-bin-macos-x64 - path: ./bin/Cemu + path: ./bin/Cemu.dmg \ No newline at end of file diff --git a/.github/workflows/deploy_experimental_release.yml b/.github/workflows/deploy_experimental_release.yml index 31a661e2..8a5ee0e9 100644 --- a/.github/workflows/deploy_experimental_release.yml +++ b/.github/workflows/deploy_experimental_release.yml @@ -64,13 +64,7 @@ jobs: rm -r ./${{ env.CEMU_FOLDER_NAME }} - name: Create release from macos-bin - run: | - ls ./ - ls ./bin/ - cp -R ./bin ./${{ env.CEMU_FOLDER_NAME }} - mv cemu-bin-macos-x64/Cemu ./${{ env.CEMU_FOLDER_NAME }}/Cemu - zip -9 -r upload/cemu-${{ env.CEMU_VERSION }}-macos-12-x64.zip ${{ env.CEMU_FOLDER_NAME }} - rm -r ./${{ env.CEMU_FOLDER_NAME }} + run: cp cemu-bin-macos-x64/Cemu.dmg upload/cemu-${{ env.CEMU_VERSION }}-macos-12-x64.dmg - name: Create release run: | diff --git a/.github/workflows/deploy_stable_release.yml b/.github/workflows/deploy_stable_release.yml index e0a7ac3d..9e880218 100644 --- a/.github/workflows/deploy_stable_release.yml +++ b/.github/workflows/deploy_stable_release.yml @@ -68,13 +68,7 @@ jobs: rm -r ./${{ env.CEMU_FOLDER_NAME }} - name: Create release from macos-bin - run: | - ls ./ - ls ./bin/ - cp -R ./bin ./${{ env.CEMU_FOLDER_NAME }} - mv cemu-bin-macos-x64/Cemu ./${{ env.CEMU_FOLDER_NAME }}/Cemu - zip -9 -r upload/cemu-${{ env.CEMU_VERSION }}-macos-12-x64.zip ${{ env.CEMU_FOLDER_NAME }} - rm -r ./${{ env.CEMU_FOLDER_NAME }} + run: cp cemu-bin-macos-x64/Cemu.dmg upload/cemu-${{ env.CEMU_VERSION }}-macos-12-x64.dmg - name: Create release run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index b973a3f5..ce4d444e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.21.1) option(ENABLE_VCPKG "Enable the vcpkg package manager" ON) option(PORTABLE "All data created and maintained by Cemu will be in the directory where the executable file is located" ON) +option(MACOS_BUNDLE "The executable when built on macOS will be created as an application bundle" OFF) set(EXPERIMENTAL_VERSION "" CACHE STRING "") # used by CI script to set experimental version if (EXPERIMENTAL_VERSION) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 024432d0..1679623f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -67,12 +67,39 @@ endif() set_property(TARGET CemuBin PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") set_property(TARGET CemuBin PROPERTY WIN32_EXECUTABLE $>) +set(OUTPUT_NAME "Cemu_$>") + +if (MACOS_BUNDLE) + set_property(TARGET CemuBin PROPERTY MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/resource/MacOSXBundleInfo.plist.in") + + set(RESOURCE_FILES "${CMAKE_SOURCE_DIR}/src/resource/cemu.icns") + target_sources(CemuBin PRIVATE "${RESOURCE_FILES}") + + set(MACOSX_BUNDLE_CATEGORY "public.app-category.games") + + set_target_properties(CemuBin PROPERTIES + MACOSX_BUNDLE true + RESOURCE "${RESOURCE_FILES}" + ) + + set(FOLDERS gameProfiles resources) + foreach(folder ${FOLDERS}) + add_custom_command (TARGET CemuBin POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_directory "${CMAKE_SOURCE_DIR}/bin/${folder}" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/SharedSupport/${folder}") + endforeach(folder) + + add_custom_command (TARGET CemuBin POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy "/usr/local/lib/libMoltenVK.dylib" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/Frameworks/libMoltenVK.dylib") + + add_custom_command (TARGET CemuBin POST_BUILD + COMMAND bash -c "install_name_tool -add_rpath @executable_path/../Frameworks ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}") +endif() set_target_properties(CemuBin PROPERTIES # multi-configuration generators will add a config subdirectory to RUNTIME_OUTPUT_DIRECTORY if no generator expression is used # to get the same behavior everywhere we append an empty generator expression RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../bin/$<1:>" - OUTPUT_NAME "Cemu_$>" + OUTPUT_NAME "${OUTPUT_NAME}" ) target_link_libraries(CemuBin PRIVATE diff --git a/src/gui/CemuApp.cpp b/src/gui/CemuApp.cpp index c502e8d2..1de007fb 100644 --- a/src/gui/CemuApp.cpp +++ b/src/gui/CemuApp.cpp @@ -77,6 +77,9 @@ bool CemuApp::OnInit() auto standardPaths = wxStandardPaths::Get(); #ifdef PORTABLE fs::path exePath(standardPaths.GetExecutablePath().ToStdString()); +#if MACOS_BUNDLE + exePath = exePath.parent_path().parent_path().parent_path(); +#endif user_data_path = config_path = cache_path = data_path = exePath.parent_path(); #else SetAppName("Cemu"); diff --git a/src/resource/MacOSXBundleInfo.plist.in b/src/resource/MacOSXBundleInfo.plist.in new file mode 100644 index 00000000..73ff737b --- /dev/null +++ b/src/resource/MacOSXBundleInfo.plist.in @@ -0,0 +1,36 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${MACOSX_BUNDLE_EXECUTABLE_NAME} + CFBundleGetInfoString + ${MACOSX_BUNDLE_INFO_STRING} + CFBundleIconFile + ${MACOSX_BUNDLE_ICON_FILE} + CFBundleIdentifier + ${MACOSX_BUNDLE_GUI_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleLongVersionString + ${MACOSX_BUNDLE_LONG_VERSION_STRING} + CFBundleName + ${MACOSX_BUNDLE_BUNDLE_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + ${MACOSX_BUNDLE_SHORT_VERSION_STRING} + CFBundleSignature + ???? + CFBundleVersion + ${MACOSX_BUNDLE_BUNDLE_VERSION} + CSResourcesFileMapped + + NSHumanReadableCopyright + ${MACOSX_BUNDLE_COPYRIGHT} + LSApplicationCategoryType + ${MACOSX_BUNDLE_CATEGORY} + + \ No newline at end of file diff --git a/src/resource/cemu.icns b/src/resource/cemu.icns new file mode 100644 index 0000000000000000000000000000000000000000..c6d8c5b5088fc39792a697af8f771de09b5b61c5 GIT binary patch literal 817145 zcmb@sV{m3)5a9j9wv#8eIq}4{?M%!kP9}CHp4c`gHYc`i+t$wit+#gf!|u1Ox_$eg ztNPTfTjzBDPFtDUI|C5iU#v`7*#H2vs|Y0pNhElDcmM!^BrPST@=pu>C$P}}-sM)H z&3_8aSw&I=P(2Ae`PUIM(~>rqmj}@OYr_J-!mI$0|C#&~{C@%fK;(h}ApU8v|Hg8` z|L3ewF2w(8|7R$nEK>V#1Di3+{Rbq$5E zzX$?bNbzy-m80+r;w??02&m|kNdu|!2gRZX!)YQlMCXfHMKH@r=w$QSG0kPH!rY4I z%#yhrHh(T%yLqa*!Beh@E}Xm?AHlr-~mnssZW(g}%QRmxNfCN5ieHL3yWgk_dv0vwjz(JRhS zWoQE0EGzc1B7QU4MPOF1FwM+=2a1GO0rgU(jUb|jJMiO5%P2`rp#J78ROAV~_F&%( z*N1$zNDA@kOJdj7PV6-hvKL|wI{zgLahBtoTkvE84I54e-V|Rvlc+U6bQURS+K=L3 z`?(_b&4Ojyu9W*HzQqdKb>v6hhy3XoC9W^b?C(L7Px_zPLF!9=@q#i)Z)V8V)fduu z>EAQJ;`aPWdREZAq2MMlCNSg@aVT*y#;H6_>+aJ#D!Xd!&|G|>$|Tddry9P?TLCV8 z1zZF$>#)I@vN$){M-jO-432P}aS1#K4|wk+Mm#?FMQeBj5`5tdkU8y_N&Fq3x@wQV zBN(h;S&@L?4$0uFg=K>FQOIhcYY##>qfOJ&4kOxZvIQh*0Dq57>zrEP>d9?0J`x}{ zDId0}hfz+&s0PgeJ*)uXecQsjaU4z#3Rl$5(;VmDd|f5c>a4X24|(n4p^ejk8YXj4DdI2e%GC>vJH z$Ve#GUfw0!Oab?ow$^dsJdTVf1BwtU0%$bGUyljJLMCti*j?@`PPHead)}Vy0$%dp3Ujl`Y=yPvvnvuo^s1 z3G90-H6`Yrhz^M?d2LKc!sBsMCvymYI;+0)kU<71A0#zvE8cPOteoH9HpE*G%p&)1 z2fW>R1$5NtMyWNQM$IC559UxVqW!%UqmI%^7}$^ ziV?7z#$uTb$sD*Fk(}tK!34nNeA@D6kqa%!Y(-3Xs4)csn1xR$QA63m0Dn=@5x`M| zvDM4i{m%$VnHPRlURoz#b-lWHf^eb~ruQJ;ery!*9rOl}uJCbECNu(eauNoz#69H= zYbrY(Loz*O-uDJ~RU+44f6e`P3N86@h6XW;*bhAQjZ@m!T=4w1?6Ba3?~kf}E~jPb ziI|@tJxjGD>AP{xO|QzuxXUkA&DsTj&-PB06WkfLEax(Ff-fb_ON0Q^=s1!qMoe;Q^@CzTe!6mUB$KVlv9g@2t-LrT6gT_K4KK>IvewXimPCa*U5qe&s&o zaqzDdWpo6q&1A23L|>*6cu(-P;p`>_F>f=D??6ENMV{U51tUxm=asl45w$P|ICE?v zUpxI#Yj58ABB`hy!v5HkLrQOd0c+$@Bj;XlPv~ek0{H^Zk*ylaNs%lo@${fq;J>pb z%+{v_;220Vp6TBHscW=;YoEzY^xb(oZvC|xERAl*6n)Csz@8&-d@oAD#_7V=#wtN_ z2)@pDtvY-iQ@`p`JPDl*B(Y7LL19frRZ0bcM!Wt8sCMH#S} z#fh^BZ+9iIe%F>^cWS(U;_e4)=}n-A$t5(zXN6StH!OG z8~EFm4-X=Uy7{+{7Yc3Dc0 zhk69W(C1+55f7qa+Qrt}$oupaQjsP4SOGZhkpLEPf!m1RV92_Jz4Dj4WBF*wnH>K03%GDOY#= z=DYKoQKjKG&Y5@_u#yYnrnC?!3s)zslHcBE90;fmPTUa=sn(i<*s}OH=0Cc|VI3jH zuPNGAFYkg6^8PsKu~~N(X+%|v3VI$Rq6@a%jw#sAIo;CqnvXge)bnh@^mJkVkuT^4 zQX4|2*&o8mNcz(*3QGq}q7p-Xllx&5+^s%XR#PF$iwarbWhfMIRNG}5H`TWk%^GKW z2&!vEPDrAgp)~*Ewj%jJ4pu~)%Rx^)^DZ0?%qAC=dA1}FM2MQ7Zh6_so65_+u zkmWoaBWUKvX947|3R|HmxCLe#S#>Q1+D)-e5F)#_D`vq>I>YHibMhY^0lXCzB<@{S zP?tE2_~P;{au@i#bSYa8uz;R*WoXdf3STy*3Fv5GmYf7SKo&J@NIGr7698a&Ux`WL z84vKsTNdDFg6Nktsq^An+y6b_!Ctw`R;UahzZVZ3tUX76(9$-n>W#gEr$59t17p&J z;@*s+8HT70GTn3f;SIjW6AH%}%-P-{oYk=}tHcSgjv@wgnWu#4%`6eZZK}~riEjV5 z@7!JbK8%Xb_J$0`QhHm>YFcnlu4l%q&eRaAm%}EO>$yp|pE@;~ZG{7?j4D_1Cg-eV zUFJu96>7~9glI_gz;%k1WKmD~uJn+vdD|~XHrO-8T+s9QfIE6vCTCF zZCJUKQg!)8pQ~$u^wcly;M5=P{}9^FqS zT^Y8**EBhn1}d({&2l-l#&;4y;1Spf|3;>?mW8i+n}1dZIItQ9v2YAudMXB z50ORo44g&FjXA?7_g*m;C&jFkiDLzC>Bot@?fIbKF5k?l248xfo&M99I4++TIJ#mH$X$Gx541l^p4x0z7w}s1T6qC}?jLeT@O^eFo+sM))*38c z4fxIkppd`vMDreZiuRbh4FWB!AppfCgNTK>qZFtWv0-SrL^=-qny4MV_!8uB*g~o2 zdNhLTtbqk*M4nga0-kRn^aqtVjPr_{AmO>jnTR_6&9BV$&uw#WjCE>qalJyBWq$G_ zB>xlE9f}v%8X(gN>pJuGT!Tf0=?El=``nvNFJm|1Y;@4pZHzQ(rLBi01psonY<`7N zQ9kJ)RPbrcop_ZN=iY4;DiUY3E}Q9usZka!V}pW8@D1d2-oyIzv;p%2!#*i2<9bgT z=Cd?H(8hVmVivZ5%mRbjf1trI&t9Nk-bd^4vw&($L$SGC1sb6B+Wa2+)&o!}^`L^H zQt<==+~mrtZ2JjwTg9P4iw?LW8Sq+UT12QGa4i6km-&&q7vz9qgXbeg6MOIqgMDbFi+ zu#=O`8AQ6!WOReA{Gylu=c7T2A#z0*<~!V0@MT z9>%(6cd$D>Qc3d=Gc@L5OIDh}Yjo3$l|`^|8RcZXJj9>WTl;)*D5f?? zOx4pb05{uwr^CqD?$6R1{3c=0;~o!L1lDq6y&Ptqgmc~(|NMQ-HRxuCGfDr;>&c8WoITV3PL6DdPY z+bwVC<~JqFK@$Dnp$xnq(&gG`GmQRX_u=~v*yBT`3&ND^{wdQ7(%mGu`RvBDsj$P3 z+DluI8tGQ@_i^FnKN?$ZcmwOXstwoz%gd-e+V14LH|ABW$XGd@QpT3z!mhhTiM~!r zAqx*)r>opZQgXq+Wh&$pgXs=;5+=71 z&r%JqK(${Rt4xhp`meudpE%|3+sL`Jo<0bQ_Hu=a)=mZj^I`m!0=q%8{QN4dg)xkC z5dytYgFOI${{>`MGwx`ht9`L`g+(9YWY7zDROe^Oz96S(TkM24IPg<%oa6n_#^N;k zRbhO6Y7#w4Y63y6#mr5iTWB#;%^5x53kvcRu0C?Ogc`+Z?mx&PEv_I|En*aCWy-<@ z0I(YWA8?QVKQsUT5BKy77?1ty{6E1x{{I{9`OgDDDhAU1UqI0R|KlDXxWp_?ka?qy zb(!v|hHTxxhhc2lBVoYgx{ob501=TCk_Bj_fG$EcHqL^V3AdjqXGE0^X%5R{%snm# zJsek?YLpBxhKuCV&>bF3KJbZW99gYuTzJd4s?c>c{P_A=v-PE8Cz{$-a#hi$?s~RZ zRsQw)WVmS)zruDFpp7!_WwZ!UPn7!5Qwd}Ko#p>B^#1-c_sqinR}SAjyTxo2{{5;M zd-pPrjSK?;VNBL~q42oGk(qD5ACnKy8V0g!@^QxtC!9JxZxu1{^8uNsu zVakyQv@*dZgS`XW&QW(tesB*-r8s#^;#rK*MBMPR-%AZeKgdqq)Trd?6ot{pZNV`i z6brcWyRaVQODzf}lTV43p=PG?Ke0|bL+sg8VcCBJ^kKc_6%({Kz;V65o%)F#pb6?0 zUx8&43HZM@mr|eE4{9GYTF4nzJdC4dR2NsDp?O=Uu?G*7$69+Re37dWz3|seCC@$e z(5QLiKWwN}T+C<1U(#(qFJ*0-9h^}1JiyG&w`k`0moxF;EF0$D>V0wGY+1Y{F1uwG zC$7zO4AY;1T50wgV6(2KJvZ&4^{G}*I7W4Es>!%a@EwL4E@w~TCaO#Rpg-HMNu)#P zhBn9>Uw?4{qqpaFm27$%@hsyFu}X+W%LRfqp{cP->aomL#MXv>@k&kB{neJ^9E-<% zNOHUo(b1k>l zd8~=%1Bn~nA?YUKi`4lKT*ZzHOZ2RZjOyu2yU*-KyB1Ywtg0;ror9L%a45EQp^vh2 zMbp%jS;=qbPOHR0Z`C$>jyz}|N`V2r8qqVIRH1#erQc}O9KU_uVIyZtR?5F4LUkkh zZBeeHxa@g!d5KH%@(DtXX9-< zGQi@sZ&=uGHXi0j@{P=#H`eiXS%i}GYm-+TV!75g>_uw`h%V`z7Cf!J9Uf&#-l4<4 zc1odLb5y=p(af7!uJ3X9F~wb^v4)Vqkg!}}^-Wzir?1(;qSrbG79VvrvD(y&) ztZgOvW36C41?)p(rir$_V34^st#5T2nsrcAm5^ML0c}xzb*uYq+$0yTRtdW4(JJ}c z+w7pA;`GKbjsUf^1zr=SfW3gDQuin)`B29{f7#mWTZOm<8G9nwp5@M@f0?iP>q)FfT#Jjnw6(fts5TEwjT zee>xTI;BK)pNK;EdnwL*6h%HvuE5c_P?@CGDkN12ZJRS|w+>dW^lBw$Mt@@S~^c z`M9gSnMRaqxIKZRKfKirJjsPn_@#gKyL}TB*{xhhBBb)5z@DTAlOvOj3A z!O91fO8K7_d4W?fi#SI++*MX8HjNr(x(=woBEDK_ijXZ*T`ttjbrR-{{_LI(E9B3q z(?_JS#5Y3FQGmP^d7#gi6BQ|~JPTtOQt2YIoJPKt=bCW>C66YhO{|t7G`?uH6(cfaYp?9A{nhM1E=M<~ek<&;?{W>}zGP zb@2qHMIO11jBd8p6+2{CUS`mbVUH($dTz|lWgW8cDktojVmLW^=shAwk7ehvuDDz4 z#YFGy5B(Vvp0r~ja8!i67@pJsGqE}la64<6e>J8_0DRY_wO3p1h4-Hvsioxp+KVPe zo}HX^dpC;nT3K6Egpda=fI>*0yVj;$u2DS%%9m>`v-P^_6svVQr8t?-k{&+3*Zug^ z)ArAuGM-LPggeF)X5;5!V`^838hPw5*?;?~I2!wiG!irsY1?zPFfoU*5cs2(6>h?6a}&~{iP zZM!xDh_)7XOwiq2?dkSCm32gezvnNJcs^bVex1) z-L4DCrGE9Lw);AmVxUVqv6?n?QWYN1EgJ9PaJB1Xqdd@rR3A1d-R) z41GLr$6qJnC)IwQId0iR$X2bOEUl8dXCq|pM-(cdb_HV}?#2ldrsb#&n;v~z+30tg zA^&=@R1iuNly(9{3)7W^==M?X4zqT0E$J3Cz{ci**!xfx} zql(DLBZgbfN&&;rn~H>9=%N6>`s$BTkTD12Y&am4u>^^m(}V$Hr4=G_U9;wJSvFu zhZ=4Vk-zb25Db|%JaEekFLY`<1yl%y1Sym!>762B_mokOfgGp@BNK0>z%fC5YYtK# z8W{woh$57fksmILpT%NBtU7wPdo$S(f)Rx0g?c`dCNFzqi^HC>*_%&_tzj+J^4)q- zodaQ4tISv3ra3^OfzR9wXJPbfj-EcAdh0oSOw#g!cyQJ~Qm2LU*J`!JOGQaPHFUvH zqnMgoiVc@! zw_3vvR50n65G33Abb=3(jgZ5kPN-D=$k-h1$^mK;V-jTw@M%o);GBCrTaJF=?5v~~ zB+tYh)}0+U9VeZTBWOeMVxs*8Y#h9yT;;e}=NWBBQd{ptY8|>eV5$lau_=`Vi71`d z44!Ar#L3_Lo6tQtTqs%efow55tR=BPW<-LlqZUyNxe0C=VbKbSM#$++Uhs*2qIx}< z!Nipi&L8#MH%X16`)$PQv^lM=VYXZDh+Lzr2cF9;k4Cg< zYcT7`_||lEiB;OS_mq>3m*X}V+>5=L_5vHJQ z`QV!V^$ni{jw>S!+F>!sBl31i(V@Q7119keK}JRWrzrYLIIu@%b0Qv+3*3~-U_EQEEe4PM{@ zIi*>PHA_cRVB9-hf4ooS{v24VCcv4Df8zJ+bR5zz0utgUKl#33zf3c(9sC97C(->$ z1m4Zk`K_Yadg8hTvR%I;YVWkx2yL^?kgi05C`oanUefLSBhdSJf;okLim&1qTpg%Z z(f4T=>-OBLe2iFm#FDNyKKllI6K0KG7LIXcM+zuqaa~T>uBv&>6X^wWe-2HhyY|5HlQ@KLno|#GQ@Rs2) zY=?4T?GP;8@z{aoL~E~dQl9TDW@7UjCdZ7+jN)bCV-c`-eQp}^N?YMy>p0z}2J!C; zz7BsokqkbCII$EiSutXVMRWsEMc0=@x2uBR7ZA&Ssng>O>(XUEwN`u;Ol^?(`5f7o zRq+xi4*mHt)jy*L%KFU_~<>SmDk-9dZQbmI)leuOs zIIKi!cd(}&h1+5Gko+m(t&~p9FkRu^>W?o+sy-u_r5}_)`_?dqs>^B9;h+ii)GlS7TmsqA=18Pk&z8AUwqY1<9}-FML3Z^A{F9_VC!$Ai7@O`s1{{=NFRu z$TGUOVv=kZ^hV&R@Q=7VwyA>bfadZFfa9q3zhH05@_UPyR-KH1?^}V>(cT-qRtT}M zPMZ>w_OJb&!{2w4&XVp9lBEI&zP~zXK}#@O!qumHfbmL^nSe6fB`*52+t=w<4 zG9!B<(@V_l)Y!u%4)mYavIXi9vrFunOu8XRl-+Gb1Kx$cYLfUXjt`9y=0XPb=*QVW zv(AY&C>v%&^Um*`A6Jq1rau-k=NCowx-& zl^`5d)3U499AX25>}_m+?7no&tgK$XEE!;p#mIz`Efv3k$$aljNObQ+aDT)464D4! zXP^6l(WTsxcXvZj#w(FUwpBF1}%N?%JP=&~qs(*F&w@NqTDwzUwE|%Hio=!pIIqQmF`p}bC z>2WDp(aglG{&u4q?I^?UZUPZS#O|;UmS)#F>NL*T1`aR>@;UiV-c(=*Mg^-u&>Crf zULyCe?ER#mud9vkkn-GS!_?aqqmB*>&10)}>8><}D;F&}ope2&(TonLW&B{pBW}O?cz{bAXHhFF<7nX)@w0pH`+js+qVN9YF(eIc9P^%qtwC85^^GWLM4n4Q zoC;hCV@o5j4w#?=I_^-XbBo*clxd06G2W5b5MSZ7x7P2Nq>Ohu+n1s#X5H{bcaXU% z#Fc#jy8HwXH7LK5_1f*;IeGa*(8jD=Alt6Q7sr0sR?q{zH(W4D0wtHuk-sl@A@*8m zl%~DV5-{tAj_NT1wLC_Tw8?Z>4^`(HpQ zv8W*+CFCFw}J@2dBUXVT$F)8SN;U>TaBxQkG zB8aH&`%I!AN&4CW2yUSsW-FvVam&HN09bPiY)R3Xa8P3hO7UE)Gu@M??O731)L~znk~E;; z71r;lhp4K0+L}gXiY2mV;M@M`LZ%tqRf=DSy{A|_t=9ohW!3k8AU)Lzx*fiapn(ix zaY*m5LydJznY{Xa&=R&;?RfOjL%N=DWez?K%EF9FAw!Vr&`Y0Tksuug&S8)qBe2f1 z&T~9cqLtrFOy&cyVFMxk(OaGe|RR?_lBiJ0NNiuND~l zY_u=nYrfnG2^6?|)mpY^yxhyFBb5+P4M#FD^HyexhCn2HMtH8bup6B|ZUGV< zHakD(mfE7Y24)gYhT=R`_p@!REmHq#6qrkc<=@%#c$l&0U1*j`raN=UU{*{UuK)Q*rB8K-c4BEG$v_Usq&Qv|A%0c6& z6A%dfvH#M-@75HAcpAp)IVbj;AO$KRldE7trU2OjJ->U5LlsM$@aZ$rBEoI~3)k8Z zeJqD52M&x>@#Wc(Crr2!Plpjq&xR;CJX#5t#-l(;GRO|8fecPjtbjaK3+#Ddg3cW< zbPY9WJl`>{QiZdN@3@Tdt|Q2sU+YdMngYUoDfFc5OpBV^phlLqhzO;Edvv02?7!&; zx8WQp4#i6$@ZO=AJqrX$iGw})mJ=h{)f;=X>f^9{r;^Gc{Iz|D)CiypsrU;N*qU`(84!Moht6%^1++f=%XdFPy;K#fPQX>48KM}Hw7i+^adXB zdjX#Jk0DHv4)}3lo_dlqDgh;OF@}psX4M>Qm9^h?np#Qhwj@4PuftQ)rDschamE1J zsg+9o_j$tenX-L?uCh=&;xW)t!kdy@NJ0ly#tdc&W2Hu*mBQ%s!jC>osU`$A z!uyJBfTyjsMl1g^O>wyHnpX7xA1A9R^n7$u~Gt(2QokCDhST&8cwmf#cqDj zi~hJW8({y#b9MqcPmXCbTq!9Pg7lc-{P@L=uxn>-?og%Hfyno;2 z2?iBB0*tJmE9|_$X=OTipF{=k7r1u|(Ple|JmKUVmZx@{RA*c@r=uQnXn6+zuCKy3 zFO}avFsVD|@*$|!T%0c6G-Uy}g}!4%dxfrx#*p~u99-E>n4}aYN>=~wr-Qt?Po}5C zGyl@DO!GZ#2vH5M4tSu}6L1A_;8w5Y;@h?*+?;-SOXG%Wusf~2mR3pFPES$fW=1F7 zRMJL^`+07kpm&;8!Q#8Uj3!NnscD}UGFVd&*xmbDtNw)gm(q;RMh-T}5x7p+^H;?L z@m1He=FwENU?BE^b+kGIt{!WM{w6fh!gB>2G4<;THA0jk!ooD9XBm5~6gy*y$c?P@ zu)yPv&c#wF2A)!j9Z)63NwWO=6E$>{icW8OLD~;iB+oH#@I6;3)+YXvjSTiS*75$Q z<8lmSz^w|WD7k*El zfk}}!G2-$P#<8o(7j?l#x(KA!_onP$r5z75OxU(1Hnq`%Ym48V_m`M>RiPc<+75Ju zagQkMwS3+$JL__`aLvhtLi&E_)kP12icCn2(DzO5*X=_~dp&=h>lbM@Li*DQz?T24 z4Y9^ie#=L6bWl6>kHfr|8UpC6tvi&ZUqRam!lQ zkK;}HFn3Rn1W>1mjUKk%Xqznyn$@m)%Ol(SW@#}+^2i%Bv!hsS_BMxq3`?tZF^uFE zpC)=MU@vlXuPaW5Vt0^s>li(O^^qhzj6$;}tlCL7p{g31r^{uO28>{~EbBk_C|IoP z19YdQCU0ku%_y)(zyGTbj2Z4Kpq9$2yWf@BrnJ~oi|>|3%;H%l;-1x+x5cre z9Xr;OCw7#l6Y1KF=4GYAsln~(KC`;&qmIe`d%)O@qeRrd_9MxTMJMP&`d@Y5Jkwc_ zZN}`T7o9&^14KyxM$DrR?C@4(h?!${ZOMUm*h7)NaIi_8F2Q9v6 zQr-e$ewfZy;q~~0a~_N&^gF#>ihA4yzS%_$pnn{4giWgQB$>mA!glh;QcP=UkFqH1 z`fAAe&kLRmQV+^#LNPuh%c`_?)(3ldl-~&3NgRVMRGuZ+8Af9{mWrIb<_LI!auK z=q3KOOMX`>L7*ynI?_g?2r8hJD|E~G2PdFkjPQN4p>~bzt}Qbas?)T4(>xBmybW@^ zPdU90Y&;6n90LZ4J-mjJrg|LS`bJ(E*Hy0XrJA-=VyzWn4Jq?0XBnJp5*s)Q@_Nl7ymF|I4{L^9^%tReMZhydSl~k{Kev)bDj5Yc%VED_ZPJe^a zIj#?|5@N_BoTiDd2H&P3Qm^bpI5^A-JK%E{)I+sd@VIPa-+!uE4$fhrhhl)4iE;bB z`(fEssD%FvDmW@ZHDrX1*ORN;YTw0U>z+N>l71O|%<_`4X@L?J{9(ww8&~fVfK0L% zGzSc*4py5hR+IJ5Oq$O8O(M+2Hp|T|3lZ&;ly^Re0{Iyy#Z*ChQE7L{(&tsTXcBJ#FV zvZ0RMFks0DIZ~jwKx$E@LqDUAs>CO4{CvGjO%6b_i(V>&MM~O;!PvNQTFilODuESc zy8ZpxzY83d2^e?9?e%m-abTEhV*c<5TMt)F-G-r5 zQ3)C@j2Xx{MSsPTbB}#n$+d5jZP-;-9H1lwRbu}Oft326^CIFTtjy%-+wd)*+wx{; zT#@-jN)j~!e#R({HX3$Fhe|x3cl+$r{BopxUan{!uGd78(nR#;IetGt{{@PWd#YSCew%l`82^9FJ7t2eq{(*4&;1fpdtpAveo`kG0d~`ZY&LMuUrKf z<2-_xGcS&5Q|`fYE`I)%gAamxMC|=35fyzPCRGS8|2qn*wa|-HN>Rfbve!` zv%VW>=xe(d@fdeK!cX9)i`iGQdZ@yn;KPH~jMeSEVeG=S)NRe18~(_G@}eqAX#2CL zAxQGK3l;Yqtin=I9q0P;jHC^61*Jb8G(o^Z=ygO9G~D(P)6&JDN4x3qW**tLOMZT# zDb%)CQ6!3hhv%>}qek#r?0HJF@BP?q3XYy*%>C|GH$T=vybsI)2A6$O ztVwe>hNf4YEg=)BW7_agr*GTtTZHfGZQ(@xk)D<=R>n_=wUb~2Ih4Hu7|KuL&`s8K zneHd~S{-n$9O+Hi)N|edGjkxsqovTV*W#I97*0TpY1K4E3Zd`KPPof`)VAw(%z_x* zXM!Y#Ee<)}XW3`_15;Y`nudS04Lo+JwA*dr9!)p>@DKA4QeH3ko`!M!TuQtzn+To0 z(D*ZOd+z+zJxGJQi8CQ4d*&Xg)We{&RL2QSMrnmns@hyH!+0r;DZLg&c|VKbFNN;1 zkUn*X%Kyv%TAsNh%&M=Z(I^1j(E-h*wj%11Hk6v_n!@9;BuRNet&q=IFCDD5EJ6#dXmN*>zIE9 z6GeJZi12RMuJ@~v&>_!Z$HqweExF%(t1|Ri`@~7J|7w@{TTyX@}q0~+7Hj%Eu!(oQhWW= z+aD`>imT_ji=G1-wnm>ez_*1#VJ_G)((8k6=*CO|M-5U=nJk^~Pq?+@C(FISue-C3rNmk< za3T4W&Frcj)bfk%gt}MA_4L6%r@hoQX?nR>-X=&;&yLxXadzfBZ@d)t>Sq4z+YG@Y z?5JEiyA99#Ml|r;$?8QsM92H8S_yr;ywUQEiGR?QsO5=G1YVh~te<*<6L=4h@7?17 zhhqB#@7{bGfX}gWU#4haO{4C}zte4X6^;0`wrm|hD4?VeNK(U(ldEznMv0&2#_DyP zJ!2_3$iqorgy>$%roirtE=SjhqKw~X0;xDD)}VN+#}pTS$}eO4%bA!%U^2*w0C}1< z-87bKxx%h28{pdBa<~~8K>U}kHUw_lJt5^k~P0&zMr?D~6?#UFh{>Z76FO)apTDmwfZel~u@Ws4}WqN{aDW-JAkEGDM{ zg?OfI(~D2|NW_r;RtS~DTu|y@o>aTacd(YB^SQ8SVBi<+4iz53O8y&w7cxW?M+PFV zXCX9Wl}1K^T>a>fD_0GYjng;1S@ z*9BB*Ul_&xX?f=ctd%ue3V$+*>UHECX}*i;;5Od|m*qO-?By;r+cSa!zhFokYw~wd4|b<; zTjhR+uc$FB73-U&WEC9IbVCg@l)Snd=_>RC0e$M-zvyl~ecGhORpD}4ZO)Z2r zq(5nehQ1^c1_9T_DPeB2T~|4#OAV=hg>pP2Ymkv%Qxv4f*<&f7(TmE_Q;n08DSGsm z6Xd|RS$V-9?tDT_&|B8>C_Nuk`kFt<|M?Y&EF%e*Yl!kxx?s)!vL5i`Sr-ovf8px* ztjB&|70k|jrB^^A^$$!FkfBI)@+DX~)MKA^%~E;tVV^Vzsk*MmG>DCXN!Om*UcXv> z?btis)g!#Srpd~Jm=lYDh9I5*zxaR$TS6A5);Hxq;mwdo7_u5o^(5OHCy9;SfIY|&8OYM^ zjXmrGTsnW!o2qsGyPzrO5;sf$G*5%M=leJtaP3?Kc+I=7 zkBp=V=4%JjuH1?OjY0;-+0(mm^7Z`5;5kQqtq9iFU9fDE!^;|=dOmS|IY$b2`3U|FRCB1}TKmc=qjJg!GoEUB^iJsXb|LcL95wVbfxvT7#zWL1| zk3> z8P+NGykRf?1KBx3auE(^&myrbz@iEBd+wI>-w$BtAn`#Y*H%!^ky3NMK)^2?ydMnW z6B-M1umUa8u{GlR0+S}01M zRnfl-SvLn&-e~yc~wS@6RXeGhy z2Dd*5O!7T zPQ?zI_b|g}Q6a$Ss(Sm=0d2KXlTtI5{JzXvAj?V56O_v#&5N(F+CeIUQgI9fS#v?;jjiNF`N+Gf+DoyGmV7T z$AMuEjU53Cj3_kX-|U@1glgm#_ske#vvmU|Z+A-XeD)aG?gXSf zO>_7Tx^UM$)-i)cF|wHvW;yulUdOQDk2fZ@$Kb-c(^v;`SH~eFksRF#^zq0w>qI-Y zj<(_5wthd5@m;4!h6gf2P$ZIEKm0w>S=`~~(Gfo34&?$j()BA9!=85Trc(zd1@Bf# zM%-2Xzvp@c;#jcY&}z#BynC0}B5^Cb`(j*PT^~SSUT~dY?5;tXj0}t!j<@VdJU!+e3>Ih5i5k zMJ8_z-`?#+7VLSVez=ldwY*+r%7MZ=Mb`&+=5?s`F{<0H#jmK!_o5D7TknM zMikQFNRvCNzv~lwP6G5UN|S3b9Bo_(l}IdR8zqNWU%J==Z}T|jOVNz?=P-XFI@d7}|Gmpw613b36N zidAC}dh!vp_X8RdgN4i}OoX1Z(aSO7EQX@5+Cnh|j_@NUBSKxhS&2GP1_=&cdmbd4 z?76Pi_yn?}84+Xk+!k1@c?fi)LCb3l!cJrtgf`rP&~V#tgd`4VEka^}Cw?G7;5~H{ zS&c6#nQOxhgsA5SY}pV1W|ZKB8U>w{*L31Tv1%P@)^&Ve25H-%c_{Sih3M6EqC=^E z++#G!)m%ZGJ!m{mIRNzuIVm^xJ=cP@z9daiHRn8jFC$WEQSfO08kyWvfc%3`a6ylH z!F%f;Vas{|b4H1YQ~Ta)qaWVv0;>?t5n7as5damjA33zz4o9s5|=3^qs7Z>AIrXItI(8bI>yxRJ3NW5~=td2X;0cRxHo#DpmJ*1N2Kkeb zNrLqfWzn*2N!IUCyQ5BqM&NM9!`k~}LyT-+tRDMwS@uNN+XYvWoaL;6W25GQFz;t< zs1|Tb&)w)%2s$o=SNzifpb975QnI?m#&%Wr$Otp#YFlSX`+Tt{?&E`uKE}FKs9zc} zXzlK}jorh|S26kQN*IyCy*Qs_FSYB33(cq<+;;EF`$jS{R~;DJ7Ry3M3@T3x`(70} z_W7b<7mAehXUR^Hhu`fzl%=R@730Hk4Nf^)0Nt_Jf(q&pgMy9gP;fnld+}?ucA7uQ z%pOO7v{q`27AZS^kTB8&qTO{N8vpjH0PjT=6cjR&;u2oJkdApx%PZ9Ee4=x%^Z)XcA`^a4AgIHWU_!ukE79}Khjlw3{#ny zMJ~~9&Us?fp@hHxc5^);0w1;z_J}t$VwNlQY<`vgQ0nST_OZ7tu!)f9W4T-?2hp{w z5yqMOi){bHNtx&qKL^LF}<(tw)IR{?i zP9as8q>3^6kqtASv3IgQ=4D%2o13|gir;J*gY73;&+6y=h3iJ?(M8*z8oc7XpI^(6 zMYUTAAN`fXrb(gyCb~7>+b0lhA+>KiK6{jgw(KhZmy3^~qjvH-lA5dOr%*t4LqoGF zb2w~lvP=y$f8wTQRU*S=N4Om!G%4(MgavA)h<(q&FYp*1_0?Hol;BLD@kv+Cf)J&r zjWWYDE{jMalElLO2*fxhAZ%u~pmjmlQGXV8X z_SC!qKzsw;yX1OE@$tOz;(5!QCTefmtAN*4-2A0oaBF(Ixf)L+)T)qdrO3(mvYs<0 zRCiBAbZBHz*@~DBn1M5D33UPltppGj0GD@_)sKp>uvT=OGQ6)KOyO?*hsV_dT(|;C zmRuDwN+@T3;h`XMlOFsosV(?l#%tE-a@Y6@UGs^{#ghskcaGq+qRlgRqb zvmWbWvt@Mt#m863s+;__l0&=o)=c$9@5hJpj?2KwB{$2td#8 zn_}t?MhdQ89agyZ>UEd9D#2xK z`f`%1B`%nE*L2#ijPiyjZuGVN2+nZCWp>hZ0Fx#wx(B)HvH@~N)v#m@UVJ3G$QnhUp=w2HHji&fvZYH_0k86A{qMm#rT0sX5 z6Z4Ip@R`%GUsJ4)5sMlEpOi1@#`%_#Z7u2@tvEwsfku#~40BP}Mi+7$0Ri<*wv6ho zh3>adN!c}6`@35W(YXK%YkUuLLV&697K6_~^>^b(5%OPak-@%q?z3LeGP`ji-dM7(3?1`AfM%+~UZnuOzB!R8{{^`PgaC}mo?WrzG#+Yb}S(WlN@ z`N1?O3(4j+vzq07--hcG%FH@QyYl7H)w|z}ZeFK}d}$m%t*5G_X)eA^wgM{JCmN9V zI~5J=eXKYyT9g=oCfBAlXSpc8d<8&^@SfVaFfw5AWPUEE+HMm04_`Yo_2`oQ2&iJL zVO+st#PjT(*h!DH0$ou5$i7{kh}K2r!|)?wzV;C_VrRB&ZaUWzcAx~fYS%__(!?8m z*X;rOij_pjGn6X7Rv1|5N`uh0$Vt2YXZ+?TX(|iXKv5boe&6-B$O!IZSY1}=U7q4{ z>iAQxV%A&^_i^f3D#zeaVPrRBjmFa|*a;pNcfO^fIUtLG-qsUZREg1P0TfzJb=;9D z40V@63La!Y^SJTTW&!f9CP5lfgL=!(vfQf`A(O?qxyJG+6lz*g9Jpq`F~+FJB57t- zKj6g`Qgh8L0^oIyXFs+j9jgRX3WYM4`Q zl_xXAsD}a}SGAJL#;`LqipDI>xR7iuZ4WiJScO$PEnEQ*+BsPzzU*W%CGmD&PI z7TXUv-JdJ5a?<3fZpqbHSfyNRLfPU$ov$i$o8#^_J@UkU|y7vf*ILD zbN;^xPKd|F<3Jnf0k$D(W-F>x*2kg6fB8d`>Jk{t_WO)+2&Z^Dt8o$~t+oqf)1R zoF4h`4!XW!tks(hM-# z(Sm{P)N392luO9Yj+DQsxuoG6r)9SQp~>a_G(A8nb=JxPk;NX^5+Jj~jM>U$81Yeb?YI}D066Fe4jXOSQ@SFC2&K8}AAQOH5@HZL z3r8MR?S5;h@*ubQS8|AkiYG1Yb`BNy1Nqw|o)h99>+?aPutVX`wUvn`228CP;o+_jwYCX`;uoKtTC(5>v(6ik(dtbww zAJCW##WO}S*@}cAZ{(u5i(Yw#mq70R0a%&lPv;vi-%0S~AW!S^_VCwom)gvwHBtAf zo@rJEliX=HaqetqEJQ|UMg`ZJelB(~^F177^OrA)6QWZ)LbHbWR6CLCQh6sg zVmut&H76241hpHOthzj(xZ$=H8H^W28SGvyN2lc)Wrq8++)j3kA;VWT(J}*Bq7Q4~X<| zdZ-&IlI4JaqD_HR2H)6zVqoDQB{Ak%>nEQ+uREAcn{m2WLzv_VI2Fw$6q~VoiM%8{ zUq#I+Gj{I=Wi=9YyRVP{DZA8IA`-y~=#Et&xjxu#t23b^3fM{c;r?jlTCAYqME2bc z<@5F%9tQQjN?AdNFBHz7?AP4hpwLOwoKQE7YHtH=*oY5=H-ZG|HJf0Ke*4hN>$9>_ z?)q*|RgJ~P;W%4-bxDVfTQsjcjI^lFekG+%T6*62nBQlR#TkDuDO+bNZtATSB+47# zXDIvOl$5s-#r+q%lE9by>*6OjL|@vs{6M_U*jwjgO^uKjGa^Q5Ty zeWeVz%oKIzu-GP)N_pC!JqLy%=%|b$B(?|wn0}+sH@KI|p+p+S1ClIj*uGm)LBr|@ zGW8F0KeOR{iB8tY(-IRw?MHIQAMj#oY-q+0i?YqN>$cpdNH~vvPbC^ktKo1j<@R1D zXY{g)o_S29h$iN(@h_bteG?S-Ny3TLa2os$iBEV2zm@}wemrO8&*AFgmxKtA&Q#cH zXwRn$tCq0y>Ec<`F6ey6izLlE*pEm3ThUzFlS-siM{6b=AZ;q}c_{ZOdvN|wkYvyK z)ssatp>rs3|Q)|e~4?{0aQ453Zj zEadyRRR4~2qEoNSSVm68v!x(8P|pq9)06A+PwK2NtFsFTgqf1nfpsMlOR1(wa`w}W zZIBCdV>)q{3tL3)6vZ2IoH7Yv8lyfh3Y3#okzCyke${#Ef1IgfuBVo;5337Nqs;*E z9Ts0Dp}JP=9grydYRa(;KmI$#;*FBl(w*7{MJ2T}xH{HAzVp7!y|c{+?e}lEHWUOPZFrEq*)piU&zs zzfDltgX?IXa5AqGYJj7x#jPXy^Vc)D&MB1q-W5#-SfVM;5eg1|q16f2w7JsUC(Lp0 zqUlP67xNFnGnoHs(cnU_&LH1PZS#lG?fbaGXSWGDEG8=nkl4gNA(s$@B5E+Vq=bcV zCIzP_8HOSq^TWq#7zDw}DCt=s(u=(DL5aC<;}W}Odq&M(I7`<#(&vnS1%8qb3Uu?V zp$4EtBuFb=^K`@SNkQL=MI~hSlo{uAYe=IlwJD`8_>dAzcvpyt>2=YU62i_^;~0N# z;+`k>SI=f$4HvbMGNpdo0Sr8mrU3EalZ5EN{Kq-oP|qvYdpQc79j>2qGsKJgUJIio z{WD$S!amr4q#%t!k?bSE>ry; zB#g!n@Kk+8d>RllNj@ZEXYAw9{M1v8QwE&Gr~lHZSHiGZqPtlZ5f9{BmB=*@(=M-+x z1#-ATbD3?3$j-HvN!A-b&;k~GVb-p(=JX)C8RRKNE?_cUna~}2KdB#jcM9IF?lEdF zPCRP~Urk6sumigN;+!?7Ycx3I&Nwa6@p=EjjX$S_2j^BR*@m_a%>T{XBKv%oTc{9k zZpC=LDI8r|hD&pF{K=p^PKnoYlHo80I18%&p^ytqT4^Fgiw5Pr!KA>+vr~k~5Pu<0 z_#T5W^|etqUNIlUulZg$TxMNE5Yox+1*QcYX(6d-a?7MJid}`0GV0)FeQPE{GcOK4 zLX^V8aZrvLyi-Ys??wrv7Qgd_@pJVHxzut9`V)^3A9zOTSM}9Cq!9nm^_t5&noinl z1~ep>K9*PZ~S0himiuKK?2 zdtvf<3AWohJVn;#H_EGkoY^sX97{E`&w*U6b_?FWvL^@QML=oIyhBZ`q;io;KXyxT z)A&<~lwY6rai$W=B*QQb3xu`kW!<^^&2IsV1~y&<$P~SwYA!y_ZU2;Hl(el-9TIYV zQ-~#ImRy9cB5DTh(e&ruux}4?l?ZP68%!NZAO!t%-urCec=pGI?JC5%HGhxh_Dwr_DGw95S36Ws{A*?p7=IK_V4!#t`|`&6-vqLv0yuww zm7mc4#8Yjn@+}mR9fHh#c)V3@iF;N1v;_y1olQ=^ z`~Fv?ubB_0uc7Q9^^uL0+U=UG-<0fJr|Lb-y>Fs#yPLvwa;ZF-Lp@2D17PW#^>7TJ z0y+E~?~F0TA($C0oiNW(`fcvsXVUyO_8N4-WML3{=y7f1LBhfVEU0B?iV!&V!K@T& zB9qdG(V7(3FMP^~eUE#Y_qupI#f#{sAO1BFSlC8DeZ&`Nr63en4az$^Add>n@=&|b z!CSqO&*Dndsi0jWe2qE##T&QOCnNz#tUOW|-=%whA8kv>w34hT>H12F`!bJQDe{e& zNp_gtu*gr#=cM+pp3p&)?ATEYq}y3hXRO7o&Mz2Uk3@xQi;KaN5{hpPJl983Xy}qL zuj+J=(z%<=vhsi;BI-F?@fKt=xEPxxAJ8!*%XGqPSGt124BfVZ1lq5_A2r)wg)ijM z{f-&9Rvx0tTI%pC1@%==+6C0$!$lN1{6>~{89ll>+>u57m`{lJzk%eag$jDc3mJ=1 zm~_4gdUC$8<(d4a*Pz7Xp_wbx!25Z9Ko`wbv5laQVvMC%`^;x@SAZ$eZI=EFYWq3~ zdkUFRr#E4YM?>6aW@DgH73eB6e;ir={=WX-tEW$s5p_uRlTjLI` zE8D;F=zUN<(o_V$EiY!aSX=2>4pW1XJwacYT(9v~YbYf)wk@dUQa~}yxHBGj)CL;i z(s_n#?z?6^<0sge$H;Qa1FU{<`#RSF@aL(+KL(Ls^Tjjw+qv4^f$gBZBB#MBrJX+~ z3r)66d$udu*C0b9w=Kp+w;#|t%C*T?e!hyv%6`gsKZjJ38RN2;;wZ$wQ40HXh=rf5 zGRCE}=ZNXrc|TaTZbjsqJ^xGCIR`Rch1P@yaktdUM-thVe-_i+<9A@vQ)!F0rT4w%xUi^)se9g4O7Y!o zKVE&N9#xMQW(Rz^#MQ5x!SAJM@(~DDdJN5>#iXprR=?JXX#ROpG-Kh%1VuZHnC*vB zp3}c2s|z<%Bke00ZVh5{T@RnoE=3LZz$Ve&l5z*C8P&dc8^k*|C8cE5H+EcBRPIEs zWIzn}o9(sZa*U71LYH6cl;W~``T_<6vHJI@MAal7_c!3fa=1xx5-ugnuMzlcuOG?+ zLbJYmsofuR!)Z`rz6su=7`_s{CsrV~J?69>Q+6LIa608uL(T3u`J;AOn|DY6_F;%T zTnQ-JOcs7pM$>YQyB|R8jkZwF)oK(w{B(!qp2*p4Y2nGu@Tj9Fus&tTyLoxn z`T3GTpW6Z2?kUsiv$qQeN4alknzSBEI{op%#p*Fyeg5Qm)~S++x9VTB>`Q@-g9tdx*m{_f}J9yD=yMoxW3r;8bb*Rz+Zjta?Q0^lc&HS*pD@GFxley>Pc;ti>pz*@v*%p9_~Y!D z;ZX1}C?1z0+45Kmf4av_M#mkR?}ffH_5W==a$8`D2~;;C!W6ePC(B1FwT)*dOzE+L zHxDjqld9t<3vh|6_d&>0N3rliegt>NF)!Ar`+xXUh#fEmrmQ36WHz%FZ7Y?S9Jxr- z!LGu=5hvkI$(LiEw61Wgk_%f%yZcmcMwz817m}=Fd2~F{)lSSp5`@d7dVmzYeJvsE zNPZvw`QuO3!Z)_)KRp70=(1#AL_P%Q98kl|(+7F1w#))RqC{9rrFe$FVA2&7WGN2G zYu~!I4(ms>HY(cjQtl__>QM3C8`ij&H=T9d9m9vi@RHUL%lSL*_TClC4-5aiqG~wC zSIH$o=?~SQpQMR2jhY2W%3 zWB3BRcG)KVspDp=TWSe1MM1=FTo0J+4cJ4n^U|>Cq*gWnzvEX4Msd!^W(7e3l0_qW zqt5CeZOCbb++Q9`&fXru6fkwuRUW~x*cO-h{$Bx!1O1dzhhStn17kTe+;sped6FRj z?MZ0Meyv8s(Et1zz9LlaN6+xY>)T{uqf!hSQt9cu4x-rM-#cSkyV!JwoGss3B6c#U zIQ$>~;$M<(4Tl7@&JFC{f{R$0Am8W)zkCxn6zNo~3(Q~dBadT87Jt)2+I_qam|)sr zM9R*w%p?`|{Hfo&9f)6J?xK^!cOEsyL|*v&leaP1XT=qMJz%^e4#*ASGvPY=%VoT? z)R$R-Xn{?SlY#;nI?d>R&|jzHHpkhe`s=Hny}+DxSUyR;9}YhzYO4tuhmBtOTsQ^>@N zAlI|E#akJh)|>RL6ta{2WQRXoIp(6Kq`W}`;S(0VEYoSLev4so6SW4N-s*_1luW&+ zD4TKSJ^QU|H z4MhwCO#)VO;v;A!>O1{Ux-?R~tnY0YgLni?`-s=CT6zrG%%{0C7exyF?YN|1x7^P3}}>p6gK=$ zFT-R!A#@QlrEDTqm@jha!>&tw#Dwk-59YY(J~`~%>Goel-6`A~SW_qs=luJKHL;}W z2X{?L5;SURe>lQh(_8%+76R!a{VP6qv`s$KVI~D5N0u3F-r{=K76d~=&eDmCI>xss zh%EZiQrqWImElH(0@R+j%79M&*n$Rl1>nj~lZa7dO(6f$)3--b6K@raV1#_Qe2ZkJ z5*vF2=k&2sF&Tg|u2Wzd_y43hBmSeB`nuQvN4iOHQRegjV4Yxyn>9L87bC{-jO8%* zyrE^F-E~#wJR;DQb|I^F`+H~JpsQIw3iYg5!p$Dhsv@aP*$@4*e zzUfHdVJg>-M-7Hc-K$ZF7#dCgp~Y~s-Ka5%nF&-pVMr6@XKFxcZJbaRy0~dtEBqh6q2*ITJuIhDXC3K z{(k){JIN?Ru!oE&0Hg1Adb28NX79&!?%9BlF_C%Mv@UX#9I+0J25CI5a)RtS)aE=A za1V}TXqhxc*eOZU5t30Hy<4cBZr;A2ZQ2BKt{?cYjNUD+I&0pqc8wkHv_*7qd~d)M z)OQ)5!W}!$f>B(eQL7^tD=RT8pFvHbylRU~Cgr_Zu0AV0A?Z^q)^b)Ya+@ji&5h>b zd8KhL$^SCa*DG*{{q9GhPw&1hr;wIC*VCl;*(AHP&P2a6m%v>s-{I89bp>x;H# zx<${V?AL`SWuW>vhS*{p8PuCk^1p9WfIMF=DG(;)SSjzkl<%Zx*sNBveVdPkjz}OY zk_5SH*F}=XcIz$?QuJ^X$58a$MvM9&Eveg4LD;XI&_=xXrKW72vn1D``Y0|!%>p0) zB0ppqbEZ0`P%a!9M>Px^K;-FmWn|JG#8hB&pUwUO2@;E_?U-~vNv>H5Im@S ziz~WS%6K-$W5w?AF-U>v3O(}JV&IiaY%`$JHIw!63~76OJE8Gv?wi1bgN*mwZwr!s z4J^>?e&*Lo$dE&#FtSiA^2cB5g&luwcqUGhBMvAsF~f$Rc{;%N{#_f9@SS_uY`Clr zKMK*wg8ox;wFhPBv-6IYWIGiJIB!G+bLqSXH4vHT-#XNnL1r3UYl10JUctbxm`HtC z@oMb?D=)2{J5jSyZ~S1;m07}DE;!VKGkJ|hdW?mp#LV8inChC+ZmB2 zC~nVUmCp&`_tlQkgVR|u6j6^b zF+TuT_`^x2gGuU0XbsEJ<2*nbrahC0QpiOs^1fhl6n4{o7{hrDuMT1EnhBm-Xz2uR zq%?zOogN;`98Wn;ms~`?pHv11h4D-yj#nnasLfp+abxdc=*fO+pL5`Z+{_RbOUXF| zqlOb_%fakboq!uujw=DpaDnwXQ{Jx69cI&?A74%iSlq>Oq=$7I<9pmrj_q)s_EU{4 z^rYm6?y)PoQT`xDCzlipwoVynrYk%6*zb2=7O0^-t9j#>i#|=lZb<|s9m}+sb=C!V zDeYQr@KRWGTae+;MUputS))D+{S~e5G4trxF!Q$N6nDv;spa&_W%Rom_TP!U+9~eZ zjC5L&weW*G|B$>J$a5N!xrfBuh^b0=ul4U#$x*W2ocR9{gKy_Ktxs+^5l0~rp}K_- z_(OMN%;x9Db~3Y|kPvUTWXSlUdQ}@N6aFV^f|clW<-40*L~~pFr}3#wL3R6| zhb;FM4LiRFp;!jWCRR3Ny2^-u1Hqfb3{n{v#;E~(8;2pRHB(`MU1LK6U`Q;!9HT>e zy!wxF1vrp+j-Irg#D`y{HRmO>#pXI6Qc(fGtTF$pGdW$s6cpENm;BfaS(*pfk-_}4 z)OolP!3RvlOpE3?0-2V`6aKEML24G6rQ8U$#HNHHNNYwiM8yYTwiA=GiT-J3Ho;B}t7hJ2guShqnqYYkgPVb)*m_KsLNqL-T+syd1Nzdu(+_?5PdRL$>F0qeKDsT(f}9mA>PK0@m_Dp=~Un&!q8IQVI97&GvSJ5<03$#@fXadg&4 zw z;AMh|31WO&I5QvgU%{~R$%mS+TPQ?>BsIMY#5^ul5i4;kx~n0B>uszzNzZpm)f{WE z5u#)Y=PvPe$j7zk5rq--Q(@KB`yP`^OfBk8h*vCTHAu>J1M}bDP!#iCGUvqN-YRX+ z`G-l=y1hT&^Ifn7i^yC<;}9{R1FTcNcU9oqBI_e|BMas(0vSzYD%Hmvs|GRTVka*9EY?bwwq~LEx8Y2s6OkxRvbG>s}Jp zg0(A#sA(FOlmw)ux^fE#FUDJOQq?|-oM6tWs3QF-R!;A)rdhj-iD2vuv690`_QN(w zeEXzHyndUl0fNZL%X1@8q}qu*0iM+|`h5QUu(yMf)7{K=f!%$dsn)a^meRDY)-8Bm zi*exR-zYB$V!jWi4a&NUl{icWXrT>x(g*Nz5e7KzM>xSIw|3?wUDOe8mf-#NzP^a@ z`OXf|qEN96*4SP8UY7dP+yxbjSf15nI0jy<|d%YSmnr-rRxV)vg#J+A+~ zK>UfbXwL1lxor$ZzYkS9u~;K(G-Lji{84`2L@!nJ*1JzTvA8f}f~jj#@&e1ESCX@=+oTtwDwi?dayYS|ei8HS2>wsz1B z{j5A!=r6qYo1fP=;Ag9dC%F3A9Rxl}lZoWM-b~lLL4c;>XLQ;uA2(k9to-)k_w5(C zIP8h&fs6R`37k1P^p4Bj_h>n+4!w&((3qd-BbE1fiBz{c?#X&EtA0rYxSGkk357ST zPcQJy8!@9pohOG6vhXA|pN7_M`{CvOhyy1O%J`l4d4Qwn zD$DlvUhqtz-!hc-?Dve=#tR5hXIE4R;A=+@Rc8Bz;N40MK0%_Z7Sfg^%wf!4FnXGI z_f@6heVSN1Z}gA~A2h*z>3L2DQo_brC9gNU8@Sj_9Cde*W+M@~=`(yE-BN-J0a--i z>WdvHpK=}dq)|HGuO@=d@h8dVJ3Q>e?>rih^`L87x!sCpbbr#!EZ=lXh z&CB^nqp-+p#t48)z``dqn$e5#bwCL<|l}lVMu$(+{IVcC=yq|3|MADjYb-b1{#z2m66Q_mGU0O zZ5xj2Lg&7`9le@f^rm89KZ2zh)63eH++*56HoU9hy!E@7yM5?G!&>=I^9D zZPN898{N_otljltjd=P{MdYYiDvH@v;B~xqeb-pd7uV>4jAB9cZz05{|5L}Rf!wvt zEx!LON*40ESg!TcdS%Tv;5JufAkkxHo9;vC?sz0vu!w8QZ`&?OCdmy^&7fwgxn5AP6tH- zWr8&kgCy16c^(;K#>D8pNk$?!_oKy*i{3gW8yTY{!IrHlw=uZEnAk=!>4+?CgA)Yn z@G@=}$oK6K>HR*EaMYaW{}_9dg10_4;F)MM0Sz%y1+)L|VtZ$AT}B&Sid&USE}BgJ z{jWE%DV>r}?7vLRcf{Tom!)mi3U|>aNhC!KAB+l|1Y)I}7fl9sRsWnpylCjIG%;V( zmCx1(?03Z5$&uunY;eAHGoQRw+>y>O@RWMk0nvE9G~hDHXfc+~h& zhN(Rby^!zvv7M1Qgay5{HAfXr(7^m1#;5KZLcbtx*A1Hyqvr?b5wKZTOK=Q*Xt`SK zUUVIq1u1_K92*29c#Auc{^4!9IN^b0EZuw6Yd`6Bp09+Cy$nqWg>>Buuss5sO* z-Y$d=Vrg-nwVhYN^#pw)W3oCrPN(W25)UKs_9#mWjp;(k-+aiml^fbK<7!m|YI(ab z1%dU>gZp2l+1yL{B#(aT;^{uq=U^_r1kzzC>1yLF#WA1QG6O5K2`d<+1b6{I1X$kD z9hgR0kbu)R<1fDN*|FPuN<6vU4}{!2N?v=PvEywnYGysO9Ir)(fqXJl64-bcgA5c0 zR&^v*MrxYn+0zIz`_~XRC)kvF7sZO*#{?allOaw6yX8ZAwE-sQBGGz*IrkTFN$phP zfXRlPsTJr*`8iRz3z;gq01GVj zfZz)42z#NnPh#Du;q}jG9iewkMCZqnCuIJN4zB0*{&1}w6!&#@LH`-S%!gxEMqPXO z$LoO$Q_yv4gUHK*q=3Gi(?Sv_FLNbVhZ^Kiho4v=L%D?APnoGY&uZbKR9(O4l&^k(+JHl|4*K8tR+B1+q+#60Q)93VRwj=qa9+k3XCMC$MfDG0#}ZPw z4&{=1IP(I64RG2b@`EPbCTlj{1XAa!@s;ZJQK9n(Q>uXIl~@>pYp@Z`WRR&!GRiChc~WTt_{kbwzfv@SBBgvB9K z`@7%T!fqEP``bC(N>nF1#qY>!zigTnZjm)58a=IBjG&;yIzu8L<(x};*Xzio66jxm zyN>i`_`Mthu~x5tzM3Crm>!>My$K+xA?^O!b5BSA_R}SO2Iih z@J6m|)V8(ujl+$hnJ6g@k2#@Lq5bL?qU4ro;(&P86!U0v5#+FEWP9nlStTD&@shl8 zH%$l`B_-9i%o-*JvMnnT2x98a{_&rimI$bPQqjHF&Dj;{d{=%jS|B^**eAKVlU`Xq z+y5)Pzv;*mu&UJ)r9jng?~h2BSO&jlWS@}qmTR>n(*!&`=u#*I&!_HMm#is=EJg{^LqeZ$=aEM)fEUE2zM=nI*YPG+(9? zn%fRAF%`36V|G+iE;3K_cjj%Ml|+%O0W<@OCAF5c_*}+X3`tKdUfT z55x40R}g}F6YT9*qr}MC@v9xid3Z$M^Ruo53PNZIgGCnmPeo43^^iW;9>qEl`_rE` zOFHrTB}d~46|uITqwPjbfM?%UjZYcNp>p3!x9N(5XFf=5xquevxDXx(CM4!>!gz8x z?l9@j!Qs{4=lf${Cv$yyapTEylFUKvp>R-GG&v{%RL7#KY{nA+vn-th5)p4QMxw1k z)x*Y$Obn)`vjsM+!eg+IB=7oBic>PfcrSxP2sVk3k)DB@}h~9$^#)+Ov?JGuzO?=N>~^4lv8l+ z2IHrqX457#OlylpD(BU{a1ZlGZ*5Gv>M7zc>-EIppBF5MHbb?Chkt3e$4u?Y**s#l zb@)Z!iQ(+Lq}n;1t0D#qP#=j!S*$754)w!NcMETcVRPSdyhx1U;mQehE1;8EZs*8* zqB;$fY`kaK=7e6AST$&9Z$dr!Wp|+c;h&QGk02OpClqGRnRDyx!Pox7>03oYh2OST z<&w=GPh>D_$CNCqxgdrT_1wQ56y@IFTBR#2v+PL973*Gu{b*rs=+fDtNs!pEzhlT(%-iIN$vs2 z`p}bkX9e*g1T_Dqu*%A-V~)lUnSn5y#E+U@zx}Fxi$&Ps8v9lPQJ6b2EshAU=7u8o zY6rs|n` zL8c2dP)6LV8I+-ut&Fo8ipa6!V5*(pce>)i|HfrsAY#UIC9q^Wq6)r^|1dHcyraej zfZn>A`M>R1AQw!Y>tcyL!AZgkW)O6kGwniB?yXpnV!k^QZOBCmu1Cp2Tgja;f*3+f(F`HD%u*X@?%q;NXb|6uU+8h3u*SH zM6-k3n%J2k9NRJKyvV*KnoHWr-jt#2uGQrqF(&nE>RZK~u`vQOIpgM%zkP9}__7C3 zrffKW3*}c>o&}b3{frT@{7%jNzFhpI_Ft@$R@4k;PKhI~w5TEPi=orAprIeG-w7I( zt&;ZB_H=U+l(OHZ&U?I?AecZlWH@rn(}v(ZA&lR7Kj^rPDFsWHyfu^t#9om4-VMwH z@I-xGv0d;h+5r4pOIg1EvnJ|eq{^#PNtg$s_W8zlC&VM=`NPD5N}So3Pt<`T=BmtvpMtI2%7=H>F-*C51ymJNN=QzC6DX7cFLAKAD zeJYm&KD~xty1o2u)`jYYsnM-S<48p#yIcXPgiFv9^FRF%`|;Ka1*H!d;Qoaro?ZG^ zTYU&}a9a<_Rv@h{8Q$nGM}+@)QK8c#y$7RzUms*$@^*Uu8h2FcYdM;p95+LTZ zV_c2pW^3y2XRvRiSM?3ujLX(d#d+cvO57UjJ(*hgM&mnvIYv*2v_pY${lXJPyf=Kx z4(u90saft5T=(s}oe?5lTt`G;8l`WZy=`DE>3J=aN&0Cgx1xZN4LX{E+b2fvNQ~tq zic7by>i6|3TJ)uA{>3qW)}BiJKG<>n&BX2}-j{ETseDUP$D?Q&KYG9l8f<{-MR&i& z`XnQXoT`qqWKqcDgF*X>kc018HB3=^wIuq3NQwZ~T3R^Sa-F= zwAMbU3|p^Xy&5nXcxc_@I{9uP;BQVh^WQiT#H@*!merX~%j<7ol;8A*C;1uDYWb=Y)Ki_C(is%O@b$&D_oWL z*~w)cLL6O8a4KDMg=B1d*Q|X9L#CfL@t#wM&?VgMg=>RRG%fs%o{Fn@QJ0)J7DCJc zHe{AtylB3Y(qBcd*k%GP;a|SFHmGw_lYqw1qd^T8zVA!Fn<#F*i~IQMUq;}YD}~S6 z7?(Y`ZZW8r*Xp^w93kJuZoa?!oQ?3L&%I&nDYi!cT}FJZS(s*72Az7Yl$JwY@Zi}- z_xs$`MI!f;2)Rb2;ynb3ZWSQsc*yfoP9H6G0{>80n!E@ABCe(9O{orLl5GRD4EQxD zVgSD_;Zda>Xnk&~wM_&c4M2RGYOZJCLU{Z|u>pY6>%kZS%fbVj_R!|edo3D%_=#8t znN2VHaJ34ZcD$!)CWni`Mks>FUTFA&Q@IAZv#7tU7HS&bb1vx#saW{-A# zxGaLIS2m~_iY;qASoQu^+7j|RmUk&Us#0X;i%B|Wd-@-KOl+Wl=laZa*t!JPR|>KK zTIat=N@yr;ncugz?_b0U{|5g~!=gp@WvIlsJ|5Fsd`d=_!XX+}&5j}O#Ta1lfw2=W z#X_FVI*j}Vh4n^4+8yGAO`F9jt|B zGHwm0OYl7Mag1eN+5b5z4D#XC$o&K?8M&^ghP6>mTTmeW2LPl%TfZC!Vm9}M9C#9b zE(<`rd{z_V;9#dT$hosn_EtzbI3YO;1D}Z7GNrSKl;J<*Re9K0CpU_wna?^xAma+) z1!wOmJMouurz{`8>%nq>udeUFrLZnr$D-%H+fJP~>rA0%-`XYSn7;r3k-88!CWlUE zKJp187yCs$?Fs-mLVd;@z?6ITA>1nC*iGri4QSXI+oiE!sF$rND~jSkW%pjcIwd%_ ziOQjK*woK(%6zCqnjVaK(_S4Z4%uOqVV;W2WdZ0nj=f|-Pt;+{Rol--(zWDJH}qLa z7yg2W4~g9~-;`sq0;mOoKQ(o{Ty^%&vXQ@qKT+Xd_xbd_4`cnqnV%2C+LLRJxJP|R z2bHs#?LaqH$_{9Cr|GynfvDADOn>r0*%qIY4jroTZ@-`tP?C@D7z4DoOx4Y zY^R+0Y^TpD{pidMz#tAWH9Z3hz(|v4It2xFE=&;146dphb|#TkI3J8xZZErW@=6?2qdH=VLPe&|TK@xDj#)H=@oYPdVjnljG@L6&N$rwO`%&{Jhh zwoM@b@FbzWT`_>CZ!TG;uX2^zAsropkqJBEd_~}RvW397kg4KTW4y-HE)Ims_;8bh zT=OjejRa$BaVxL&sZ+P^)wKB*)&8Vo#Yu=jjA9kxiErzrdgSY2_%&PtgQca@RIcjC zv%a7TFzs%>3xFCP4Oair5g&A|Qy2h@MC~@Q2_xSAkqC~O3UOwGp~<>1HJSC{fA^N6 zfz)?A?H;mv`G2zD&;6Cl_D;J1>_2#<+|EDfxq(0Uffc6p%l(T3gL>Q8eu!>uQ&S-~ z`!+;(^0t?ph$E)rB!!FktZ*Jh4FaI$tOp1|0l<^GfFD!C>`;s@kGvS!T{OpI>yzwc z5Es10vGFyKe8Meya1{CZ$1Jzp6I~Vs{^)%A+9e=!=2h7rpI?CaEybG0C(XNfD3l5 z^m-{{oqo9;zx#LK7~U`7<-fl5H;fSnkDF*S4hkO^Y+n1)&j`*gGgSHMwAnTD9bzq< zTa~C-%MrOvROrcTL;T?D`GG!T8`}|j`%xxuy(n>2QyJSO)g4u*DmfYL#8r=+Q@O5a z@5LNL5s*NGu^RJuI=cB>0kF{;l<13+?T)RK`PAvt=}|91YmE^&HOW2_qUPWk`^1TI z;hxQtfBpB4M-G&OClJ4P_Gk618#!W{yipxIt*e%B?~b8CJUTO$0lGe>+!dLz)51Ko zJ3hyk`SDoGsf*$8(zIiN&JJKKA_k|=jc7AE4$CHyj^@vte`f$z1;6R&|QGYn_f<{Nl*Q@efucELWN>W+4V#WCm* zN#6x&%BmWO9nRbUFc5qB%ef>@8+JXPp5RI*q4Qe+*u2*6+@YqdW{als%fcYeFzyT< zzB#G1*R1y2BYoKD(qzIT1}Uxp&e^u9Y|@u>GU%!EJk#8dmw@#5{ICGjx_M5Dqm&cG zw*^#j6Nvi2P!3i)@d5!0!Kby{voQBtKBAn-U*DrAv0jC6-C>o!8LP6MUZZ{X3p_hR zxC&zBW;MP64D3_qrmvl|#KxVXU8mK8*4gkH%BL0Vl;HV21KcGux>1a&XZ(|xIMjZkT-u-Ltwl}AaX-!)RV|@cwUsr4D zh=x;k{kle{Asa2R|G7|dPzRtr^OOT;xK%k?4x>u6>%udN!)ibnB#LfjERfFn_H+r- zn%ZK9Z-i^=kmp6FJ+fOXqcbEe!4$BuXVww#Y57L*GE$sqG7?YwGEGn{@Hn%ws0KTcV0fBZ*dPWM&N zKu7b~D(VO6sVVdnA&=>5m}(i?X`^nX&300ku^6_^pH6#f8*T4c2dTrT&6upHLwo9Q zz=w-IQJ@gA2zNdxLO%l#Cf5`|`r*%XtwX@g6W;%`CjR-aLwpBdiRouwqra?rwCmBP zo{>7Q-(mN)s;-0>$N^XK2c#8anqq_*!&v9~vYTzxjq#ytt{Ic#%<}q(ax7O2A$?=Q z*|C$8AlAE%)0cY}SPY}Mj+d!po7$FT@H%EgmraIGNPPrN7&3=St@lK12Lf%w&Avl@ zC%1DaVtl)A~L zLr_l-p~+;t_1PApVVh=U##m7c1Ne-3Mlo<05wnZt1%Z-8##p=Cf_6v(0n` zKe^fF7^d0RylHcUqUR66$Dpt_+HpEMrz-&UELv$EM>jj=v)F0}dxG`43caIcu7`op zFk-m#W+PCSv<9v2@=1+o zteK!B3S>PaPG9D;0BE8Q8tbemS+MmmHoCKx2Qg+u;1vgW46??V$#xjxdpw0sp+gV; z(sb&m1q%M}wKGhU5Vko5V*OdBsp-s^MlU*13LW5zfgNpKfH>@+l%62-#Gyz}8cdUW zMhMZ!h9fX^Er{bdh-2h-5o5jalv8Q$jcG=HP*w|U{BM!UfY)`S+6fPJ_z?#U{oI#k z2_MNruPg`ORF&c0&1t3_yYXfQD7UB46wodc(Yf9NI0A=}B^`Jv0Wn*0}srfE{xqin9YEhB8DcXEB1_o7HRo1m8tbrN$r15o9#ux8_U$3UV zt?PRa&Y!R&C^X zN12#$i-U!Ab&#TrFBFVJ=YAYY$NA3wgk?RR{%_iVwHL1f=&Y?e>(JNB)OZ!z?cu4+ z?edi50bgCh1i>)tQ=3=r0WHY^qOedgPtDR`jj2EZ#&p%+&2Gm5V*;)-Hv2$V6)@^2 z1nTPLTs7sr8>CD7z|ujdd(r?iMovi1S3o*2p>UuN{lmArsz`>gX;D*M*hv?@ASzmr z9E=!%M5xQf&eUP_m6OnsX!2+LwETP)fYkZcJu>Q0?SRq{at}ju%MmOw3c@sfjiIEv zt{EFJ4xA}@%Mqr^P}-)L6~rg@d~Ca+6R$^VpRE%x1vo`^>OUp4Uwk^?MBUmMb z`eIBIHZ@v!>`0lL7LzhI6*B@sV|oCE0dgclC=g-+KnYzJjiViYXpRl0%Rx?a6j zu8pQvjytRv+lFZ4xcAf6&SwE=&2lHIqIM-s{)P*t4F*0HJ8m>aRb!__VW$a{ZU?MqQ;7AM*q6gi-(wJt zIhQjHqa|C_j2V7B zcFAGj$TvKzY6zh0c&2P^<|(_>D6YTaXsdBuOO=ha-EwXNb=DJ?dCJq4IWGWgY}WxM zgM(dDyi%fv9jyMHk7L@u!%NduR}DkCgLfP;V>q2fN_qV7w135x-z?m_6@LZj;oZENHA}*?qb_aoJ5J9ilrwG@-Bt*P!`E^j#y9tPE3kf|7lJn9w*}7K!9R(G8(Ox>?NZgz@pixr+QX!=sZAa2 zj>W1P-LHt1yCze2Js^{FYB$mx-~K&)1#1|D1;{?`k08)fwvD|Ij2XPvh z!CmM~IdpEI@(Eq9ufzo2b%tBTSztH-;&~J#6?;ptf7oVpu=nr)NFMW}^9WusC*I9x z0qAuq1n1IOFm;D)w@kMorZ>R@*sE)(vyn9T#+oq=UlX+lJ52hAo;<7vf!j7s^QkHC zPwP*N#R8x@*$yWm@j76krwM9ax>Df2SK5K?7|GfW{!Z86ovO#_cxNrcis0y53WcSY zgYmLF`tKH_EQc9Nryk&|XzRfe&4s=;fz?F6c}CAmXZ8%@dAKVSpZt|a$=~2+zx;S0)uWsuY`12 zT0@Tk_IN4XIi`8mnRu~HVMC(CCm&n^Jn;CTa^%>FvTf6Je-~ii?(O)IktKW(Q0uD? zt=Lqy4V`kHd}gOCbvh(Gd(?U#OsOl5B^Bekw4^~{zo<8oC3Ls5BWP_QVKQrPp`)@z zAG8>#pRA4kp7@ScBdHSiJJmSL8t=9Pp)OGmMiU)Wm+h9rR)G~4Iqk*o>0D1njOl3a z>!W9(tu{3=hZ^`OM&!w`ejID3qjOpSoD6lDf)!oMdz!U&lkr?~fV!4CiV>n2mK8I4 z7^%y8PCi@#+;iZ`auDC%+q)fqz;mK<>E4}X8{P#t8ZQ~~_Jn8mnlUsYPkc6tGTR1B zYohNeegV;Lv5%H3z%XnSC)8T*Da&j3=k zP+j|~s_vt2?xR6gGX{TE$)S`#A196zVC9;?NQ7AIe90eb#mYRxSa!%&sG6c(^0Q38 z97}nkA_EATwoG$PyF#0E5ybYhGul=F<~|BPi>tY@F*&Rn7dR(1xzy-ZfReS?G4O>m zezNNT{(A2NSOlglmz}kECA}T zSNq)2LEBSbovVh(Zs3&%;}svsl$?5&Y2Ka9K2Cgs)H=OF(7*xDGI(489K?%2{2A{l z%O3p9*kyb0Hv#Zx$JCG17uBOay78naBG}p1%t_~d3KKr^Qv@F6RcX8NG`Dzx4Mn}1 z4FLS=!VYSlIP$88e21-LRPD9hoRHqA2d~Lb%D=)yI^4KO4(%tP8sZ?g1%ds6jK*{m zI~G{BPyJUzD_`*=tN~s zw*a+uoJ#D9NbZ0-9@f=5BA?Z8usMl_QOuFR{&2QKUr>l za6g3U%FZpD$_vijUEXsyuPkbXJW%1#Z$1k^ z3|>k|J*ue>+uG9=uC2*t96hK-n@@*^FDFlHo{s{3^tY~j_JKzy{V0&XG4P@b_TqTF z3nwa^;c&lNZ#mhRdN3i88m6BGc5bBuIODq{4E!lZTZ92G zF;PJ%$0k77+u0d1ZhfxYySe<@H@>u-w|x^X0-$?Jh5fJH;?Jyo*YAI-+;AWN;?f3m z6*-Nt?6!F=0!)-v%W7bh`bSpiKplzOBx}`UUyYu%kxauHF{&1O{BO_Nc@W{R_uPcP z}Ex(9(@a?x3M4zR8~#xoZG>_9ZDopC++rH@9se@zF!(D6Ee>Oe;495*>S zt`G?w^$#3t0NNZ}3n}(QdgmjJfU6C%TA@Ur#?x69oudb8JFs7DFuNle44SUBsz8u zMT2EhY;`=jpI@2NGl1G)eP*pETh2y1w9&yB4Ie1#W%OKd@NHCrmmC=IN=+;*Ek(wd zHbXG3BI!LIraB;K$3$7?6~Oup<(7vYEB82e@mcLbpbiW)#XKM@t&VmOs|}EF#&w&z1q?BuuZtJsVT&jCn{nhl z|LmR6O;_&S|3o=_446l8eGQWB(Cc5AD=2UwR8zzxaV*)buP9pG ztO}!^I@{?KyxSOYYTS&IVUpdP767)bHaHrOpRXJ1K-Q7ZvSV16?dCykCR{?YNyi;i zkImSiBHHC)@Gu4C{W2B+UIl#c^Y`G3K}TBDDVQ&N-Ua1+JPFswfoz};LbgjAb>>Ma zkc6^FX^^opnRk%tZeUOl7uf@3KG!kIbE0dyC`vnE_3<85yd0;WKkLU|TjF0_ej#pw zrYv`10XT$DY`PVIb)#PPL+y^*)Gz8{3w0yL(%!Du6Ik{n>rjDAm4lL}J`SU5iABJ= z2x0eDRRz~J3j;s5iM9#LoE89O0;v$K3$Gi^jJXn*yJ#2^VFGlC94g^Gj)>7@!f zCZESca*$UITG=jEm3sij<%7VDo5}+RkChv4y*q=RHoqO;FL?9S7vVO5_pR92Fdsy% z!&SE&XV7*j%eDc7Uo8NGjdJssG09=e9Ty+CVV#a;jOzC)=<4 z|KsK57wxHEiDt7VD2MR?@N-xIv{-Av5!7u~PFx8ai4y&&`QzcC##dVfR9-mSGNrl7 z*|#2Q923~sXV5qiHoW~zb^Nt@G7K@aAlF!|aq2Rc1)!#dZ8rx-d~LpyfU1v7VAW3UxBzU}g!lH>l|Q@j_Hu0Ep9uTPt1c>+ z@50B6`K`bH&O2d(-{+1c0||`sfc$abero25c=)vdI9gvMEi) z1uGx(Lt1^Q?Ks!c={j4-%|;s7C@RMeF2&Go5_v8QfYX4qM!wy_+L3<3$NDkb;d-!k z*g9ktS1ajkuD=aK4hLR%>e|rN2;6g%30!pxEnX}so3@nq;|k#JN2k9Hc=Od4^gq5* z^J)v!B2Q?ku*;JWd^;m&KVsslq4vu0Y9}3{c9b@kz!Bh$Ao0WmPpbG-fw$g1nc@mX zV}=)i&fmJBTzC2T3^ZBct=ZiN@Cg9_;Hs_wqCISrH?XytWJ1jrkY};Zax+wO#lYCJ zC%NgzVnvLVFlw0V0jM655h#g~%Ue4Z(I{f7zwHqx} z-fE}PtrhffWq{u3N=q_zJ`1Boj=>%quTT+JnW(V=paZsu>xIKHXzIm*LN=*1pJN;L zr#>km5ze{rSlE&As0&~D2i81eX$z9;fXd@vrx6v?mN_i|?j##4p1a^v2c)t-(VT=( z*F@A1ia?BPF=;t+&CfgmD->Zh+yEG7*);jabAThb4fy@P{w#hU00-NIWI41RAh9(B=uN7bsz~$ z2QpETU(*lm#;!z(9}Y#xBzaQ^D0pAFep4x%x0d(Za(B7;zK2!{{*?6mneey2^2)Mz z6Y5G=0X&fF1V@{}dofT>eAZ_klrQ!xc+gHo9cM?_jWJ+A>%s22>=tnYt8k8E3R}HO z@uHC?KmG8GmkHj+A$N z^yaFcaR2%%FDPH{X92uio|#zahbACw`QDp4U^V%uZ+?RbC||~i*qRA}mruoO!9kpQ z7NtGnw74tR!54yPoxLqU41E0ebyr_l_|fN-<;Hs+EH^!XPXO?scA2+oQPd6#jYivh zeTT7uZMVaiOq(4#I=bLEj9h#z0G}8$nH|Dd${H&x=11qY0JJ_;rk%vtl~7@Bfonip zYLckVIij^H#Ko>UYrzmW+s5$O?z%n0dkp~)dYNno<-xUaGrk zOe2nL#MnRZJvm`rAKr5~7Z3mb*2^xR?8jA|`uE&?M|p(z{~Pf_6&GqWStV2RcA`9^ zgQDph6R~IuyK+f2F)WojZIY?tq2vA=OMP~0PEdmHpBQ=a{fOcJOd{_h)Xy?HMLNH{PoC zhEa{I!x!~xC}-MGaaJn?Ro-X_M<24n+MeCb2bG(3HEDA7F5ByoTqk~;{25@UiRhdb z0Q6P^k5<->x9;~6%1+QiY%UO;WcIxkVId_raoV63)((NOXdlOA%w_{Ortj>I4IDpb z-n6wGUS41R)B8VOcmPgW_;&;U{%fx;*I%?7m&{lMJb_w{IDzZNL@Z(QQ6{cZPDW42 zs&AL@?JNzuF6%pA`sl%)Vnqzaj~H5PI(^qJ*TpP2ZnP)b$9w;MJ2sZ@dF@q&KZ!nN z`NSRfm5N@~2YG?xU!~d1@NusJk9YT{T*iIp}AT>~DWv*JudDlv!pkc7yLUx{rpU(o&660<`VKy4hVe-UXtuF(&87S>}8`hI6W}P`+k8iWx z!$NFR1`k`@29&Ma%X>b1Px;eNO@9?|@t*DFpT6-$<=ib89^4Al3124~-v-n_9Tev4 z#MCDQq36O-k0SI^2_mgq#_^ur3x;kle7|pOQ2VY(2Y!sH=K=6v!UFJjUw&D6^~7g? zw)Y($zqvee7;jMGBigbKi!%%RtDVPB3Mxm+xUJ@5U~6&7*fzp5XAOZdGPG%{Pd&cu zZ`yg*ag$S5U5HbWIV}Ka9(&C`k*SnC6)06jDRX^$hpqaG7O#wEdyUC`A4_>S?Wsed zI*t#KcxOqr-Y!7Y$p<@pF{o_bR-QPquKb5T|42D-Xxgg)R`s=4?1W@Cd$bRuyPH?d11<%4jA7`RPd}%!}eo%Vd&K>Y`181by64pUVM1ffJ^`D_w6p< zd)+m-_fNTGC!c1y6Tj2=j*ov9_x^Z`l4HV;YCWi{#zwnb+$5_^ZEtj77>I&p9eHo4 z!`1Y|Wrx5wC)k)z%BIbEI%Yl#KL>;e;qq!LR=qhYk0 zXb2!yJA^gTdxS(oX!ri`Xm&6>)8MT@UIqNgjdzqk_~=bt$cZ>kmjC8UuPJYP$v%C2 zR{O|KaO0#-ymZzNCTGTTA)ucZ1W#0BEGu?kz2LMuT(2o{tP>rVKlm!>>gD{c>&uV4 z=_Tb7T-8in-i5ROjePpQ1!JN6e-DytVxv;=uzImqo0DBE`xQFdO=)O6Fy>8dp9#qY zd4MP8RJtLC^2B9M3qZ6|y+$|n&%L!R^@Ju4j;T!p7pbX3F}zA6`@r=q1Ksd&5tbMk zvXy+2c_zcdz@;tQ%aeE(@U!o}p*(m1KSech*^M6#{g+>TZFx(6L1=U$asqN9qVdfh zI?GJ1_<`P&mNqRA*`8v0QSc(sVliQiO~0svSp3Y{mUSn~|M2D4l&`^yKT{X}_{Xn& z;1lK863+a*0?>B=QY{*?G-ez>HWejE6&i%vY%y>BnB3XwjU$6u$M9pk<79iqwWiS2 zd>teE2{6fSJ_~@`%ucjx(XLPIs5+|yCiLUPsG;) zhl;h?ra<&b8;!=mZXOf|+_J6$c9i$tdT;sV_k6VPKas>U=l}loFE3wt1%5dQm(%Sm zns)Ge*O|B^h~{_tu0PgMlX)X%b<}jFFVzDX)}gvh=<2Csq}z4j8jeP6 zB1jz%ysbORvGtqF&)_QHQ+M8%e5PZs#)~sQ{nl5Nw>%#oq467od9rchvSXaork>y# z*IOijwXNq9ae51fb);SltYekXsSUJM%o1Mt{myGIF8}PSURt(qiU)JkrK9ld|MP$P z;c^I9Uwjs$`~TkUT8vYxld=oPFXXIlV{9BL`m?6Oeh+|_Nxc!GI&B>IWKrXp74zZe zv;eTN?xcEO7q|KJVQo=+gKZbLkw#uajDV_1c9{jijt7xG62#@__Fd(shn^_^_8spj zhw#1hc@!=JKl6>RDt{XjYvcdl-nR$ab=BvsgDqQ@ZOJceV+<|WB)ln<0z)uiN**Ll zr%8D=h0bJ}Ht94|CNmi(ff@LNghHlGXOc2Wng-Gk%quuRz{HIy*kA|qFb`uJV{8jy z*|Ka|e#p|*!_w*ZeZSwg_S*ZLdnK83q$_dOy=$-Ed#&|bkG=NVk5e}QS^gY=8l1pA z`0HTJf!RC5lh#Dqs5Y^q?#aTFgmf+MJeZQ!;E+2J-!%A@=UrI-+pC^m&c=_Q%p-i_ zt2dQv?!aV=$ya+ZdiqZdgY2BPP?RE8iEW8kcH;p=FGwO2M~MyT4W4F{yU3x~txQ9< z?pxU~{1>#4w?Czqq+Xd^+!>{FngFuo;oYdYJ#E(13Z$rbfZ4gImq|}WH1ZsK+(4%2 zwfFla#1@+%vh(22X9^0|epP{3cH%=J1$zPPj355;P35xdZjjk|9C$hKNB`mli1VJxJ+?I#B5olt8|Tfve{Q$d?THlpjR<5;CJ|ixWaO_@lELXPUN9mQzm{ zm*0HJMdiQ$-1E!1r(t58L)diR_VTBn{Yu%xYkzFQj`(0!eg8k(CKFBQUK!9GZbTG$ zYG75&K)u2YDM{re2J0Knl_dRPxfrzOhgfP#Hgp4QOxSwZYuL`mE>6}=lle>lDly9G zlE*#(2|97sS+U~}cJ$#kU(eBlIY8C<=q~D2w`FV7Ht1nH^Og+hE#9cI>B#E^H>X*| zGa?DDX<+$|z`FJ2k@1P;_y6|la?=mC^eoO2IpdU*%3EIX%<{fpdZBKw>3)9>R@FZT zYdj#t0Z)I$J$a^;-oP5{b->5qZl4e6+Of3*yJ?%3CH%tgAH3?h<#&JTx#g@mo%s(S zzdy&N*7ck5BG$S%`|G)k+Ais7wQ1KWgnj4Vv49?KEIgQY7 zFw6VoZ#)cPdLf~nRe%uIt0-b{Y4j-wQFYkq+jd6t8c!&ycf@1j8DRKKUZD!JAA>m*01`gZJ?2jN0fa+ zp#lxfyp*CmgVVs;V`HQxce#Md{>{H>c0hFpl|pE8#na2MbV+$Q|Vr=D9bdGa|RjmzCTmdYc0xCh}nQnKwq z39AzVX38=vBo12ml(HEqS5W|%DEPa6FMPs=^0rqzqr4Sy)}Q#!Le=Enhjx_TdjF@( zx9-7x|Mh2M`HxSEd-*Tl<6OqN5GJ69f)da6iAy^0EJIPsI!%;G5}ULE=?m&81)#G6 z5YxblJW{ad=hUUlM4&C`;5QQh@O|^k5bs08br{0uE>$wi!|b1o0ja?X1R;*} zT7>?*Np8=hz(Et)I^6`>WRljJ#HK@;kFok^fZaOSHpjWj4>HoQgi9RY3#?!&L% z{EyFETb_E}Ipvoxc>yKo7EVBCe({se#z!{KEWdj91LbdS-dsNOy{+Yr2X>XEee5?Z zqa%xv^&m)kZ6~uDpGp)5rjk2QPRFkP^Upu4y#6^CmVfn(3(FJnb>Df1eOTT6AvRe5 zA0E0Yr(y8x?2kPFT>GmEsv}B4#4ro3y#dl9jMZMoS*e6IfD;wj>qpRlS9YUP-3Y&s ztWW`9)vrnH@lqa1l%MjX#bvBkaYP+jUDIZi&Se5@U0d zF;f+sB}c5Qo2F#)C4}UHaajYq8`hp!o^s}?_g*l1xL)ZsgeL(L)ks<2UU{d`Xo^+O>Pxk0X}Y8?`qGx%)U(?m z)NlEL%Ssh;*CiqHOO_b6(Bo9ySpajH0PHh43uSllStr5i6+0*R)8+_BSctVX%#=!u zrU5)8m~xRJp)OQA6=>`a6)*`jq&gkocGUPpbWSc$F$vtheOvjhzx>E!%dK+wOm)Y{q56Jv(-TzOOut%Z1(e zA&vdq2Y?9<_R~%}p`3|Ji}OxBxjgxdb>-r-PAktkcYV1CDF^*L9_r~zKM8&L)=lN@ zAN{}OfqiiJnP=eak4b=!{rbHEwF3{131-r?W>2KeiJCggS78D<&8wl!@YL_FCe6ka zaR>GaUQU3JTUt6Ab!EE1!SMgRjaIl_(9eGAxA~5X7PC8ctd-165K16Qh$MDCPLcLDJ zz~V%}AMKp=tGg={bt>!jE%%k*{;N-y@7}kglryl;!TbJx>W>=qH`{`V4g!dX7eDt+ zSd=LTHexrZDbV$);PsW-Mi1#pJ~OkN)4o*4Z|Tl2N&t-ih|3nfResFyTqc07f~=Hk zfs5&`BBE9&^~>JpStqD6))VjOJu(mvevi%ITYi`#AFu6fh*?vtHPFJ8tHq1@e_{hB*0>}fiD^H={%HfRfjFxA1ZHt|EJ2; z-`gCUe(NxyYUz)C>xqGns?h(6YzqPol@SDusg`fKgQV&U2aypw`_?r1mNpdzk^kiJ z){D+@K|7S3AB)T!Zv(0lJa8v1b}^%3q%9L95WFfoq)kz^h*OQ+#!MZlsY|&k+uF;H zF|~h~h?E`7ov^Bt21GF@0iLl=!?G2(2d}vCj`ACS_OWuyW<0;X2rGJkJN|FRrPC+A zj<+oFduxM#4*t_IfnsBoxBSMuwI>(T?^MjRwolSRNR~Oqqd9S` z?JAZIapi3WWl~Ng<3t9rhvtQYPTeh|&C+ycYj}{xsbA%S3{RR^13<=N$(dy`p9w&P zW~mjpkjcx;tW1)VpA{U|GG(iolrFaPC#UxrVu-B1o_ z;ye>~RWJ$oy1(@;oFATU{9XCBNuK#h>&dw7E$X-#ysNYwW;Z?eDE{B)H6Ti z>1=Neb{w~|?I)+#Ni5wpSJ(=Ah;}?$^5mdRC_gHU=L0ketUt5daQF7|AO83w<$qmq z&D>rda;cA%^jjM@mtXsn50}6G%FP=5BTSehtN{4R^$0#3`FVdiJp8Q{Jn`y&!ig{; zN(UsV^F zKpoHrE8(G3c2dR^I?b?i8ses}oN~&@vqZLN+}Z>}gU%?3wWH~}FXbhM4y ztPJjY9O;Iw6B!_5M9UO(g2gd zPD}#t`TOh2H#Xi?-u}9uEw6kYzneGLMOm%sY5*SEwN(D>ifhXseCq15btfKwcj{^ zo#@;MBY3`>zMyU^ft?)%iaFG*U!(dkNI?^E3URQg4At; zH2hAQiH%$~W7uKaP%e6$q}BgGb4EQACN}m6!br`NiukX%fmCfRh$TYT<7K%D0pQ9X z29X6{2zb=}l5$my$c(~VCV=e!D55IL56r`IM5Q|AWDX^OSCSkR-tUNA zW7LL91tifvZYASklGI5KC~cW?Qc)KWof;98i}-9r*aCrPqnIqng)Aol(oR9==I_|? z))t-{xOeA{^6pPuRX+di@0B7Llno0TYvbwr(sOAiO}^6byg zS@F_<4-R3cd%Wx6a@`$U%D1sW_%qM@M){4Ozoh)cGcGD?PXhlK54-m4Eua17E#*C* z`9its=8gE6C+fW(OMc$!W90Qd{h&*vbglr!e>+MTq;6XP;+6b>`|*1WEnhx%Q9KRh&-3BXm$g0m8w066-=irOt# z^j5cpE#ErhV0`Md^0pC;6dc-UA>nmYrv^KbR{^v(%_{}e`-19Wblu%uygm` z@(;J*J^m}dgwLnng7**bO+zm8d25un`ql#Gtx{eN>8x+xF-4@W1R5VYAZ02!<*W0} zp#HRg_FxC769osS19bxH)6DOvIswQ=L$lZ*9a@YEl8XG?&opNEEWmQ*9vFR$=v*d% zfeW}E#sn}vfa~%TR6qF@QmUIP*t!KYpp$E#zU7K(0MY}b$atnLjc^m#SSU=}+>xg< zuGT}zW{I_M9|4bcDMLF zf9knEhF6RKX?fYRE-vS+$Dmo|flK`_-gH~J^y;sc&wcy0@&H~+(mN6xxXFj|GuE>{ zFN-)EW{_{-6Q`92TBr`H-MnGyjh&nEN zXni6*5J)pj#n!I#Yz?+HOqV_m?kp2B6ljTwD@naNYmu0t0sG|ygXX;K^~N9{eBld4 zOSnY9B(QzYuJTcQ1OM{tzf=CnQ!Xe!|AJ?hpT^4I8BaRDoVFISt0XMp?ZR8{-de8w z=6A{`zx-|8-PpMoeVBF8M?7$i&oe%8UF$bzeGPV01S$XO5}CfM69EwO;bCe6rbkXVLyYm|ld>P4K<_nHv4a=HNsn8U%8qSUpLc4CzY3DMZkT6AHVRta>l9a%87WB???uI`fTIYZRH$kZF1gM<(P*U1&h6N3iR0LXNLz;)@bE zV22bZ%_=z`U_KK7O3gVu3eVv)MrC*>V2oZsbeYNw=rQn8cEFS4(tDI6$l!D!-p>=v z;PVKLIs*W06f2nd1kW`yF>_VMsiA~+$wSDBL`M!%WQ4)$!c#{kLF2pbToUuT*sFoP z*b_Ph5vzf+XLs4Udw03~8@HCrzkW+O>(sU7;`7fg&wI*+h)*of#ud(!mRq^d#Zf?8 z1`>i>ixy`3W;KDNo;s;*Q5f{hR2{(ApER5FFd6y8S)#Gkn+R|w#S(hV$zUHoI=Xic z(miGSzP;ru8@HCP+;*3)Cf1*Fayet&T1*0Gm8YC{cDdlp4dwi^)|YcPtS@Jrb_!0) zr|1^r$!ku;is6L%qn-R#z&^ab%#FK8miFMorn?H?%)9Tw9cAh%WDF_gc-O;nW1K8U+gW_l<7eA>;+cJz&jf&y z7km`6JZk@A1u!ZPpmt9#`*9_}d*2FCy{=hYMW-}mI5bFM=$bU}?%0UUg2X^EXj z?(XQF%^{TKsyg7;Ng!pts;E`Sk{cJAd1+DzMobc*%Qo$T&Y1fHW3LDv#kDj)9*GH{ zU;-$QBE?sT4gh`-gZRM*m&*6=-&C%;X(Q@&0P3T{0nd+ptihl^5$$sV24$F6VNiWM zwS~xu;8A=fXfHk-vIlXWKPARxyPjR($^_T*r})kV?_OYO&*eSO^nBQf6NC0Pu##aW z3`!f=xJWo8tEL1}COky}3-!U8N6VK;bKZrKSUrH@K*KiK!h?Qi@o6d5Rlc77G|7X| z*#8h=?_reseiSSS2S9Nd4`SkQ+4GqISP}01v(&KZl5Nsb~-p7%= zdTD@x$bohM*Vq{B`hgHmto-djM#7?#hlsPv0mLN?YR0k;aW5N)o6If`P*#-(mWgL< z4tRVbtl*&~!Fpx^U4|35&iowggb`09y&3ejqcrU*Q6`Z`%R`>NM)oR*#qhE}1~|*r z*di!G+6<` zxU|vih5Kjlziqitvq|SP0hIEDllGN+me#P}vR1oLg}YS+RkA6(9hW4Jq1p(;dbbX1 zd9-8Rz@{76W35%I`7nPooZ6;@Km=Y%t$d}L+ZYguy2+~pp9Vl?8>^=a;UOaE0)Y`U z96;2aWmDZ=xc2wPT}p9xcXzj<#a)WS-o;&tyA`K+ao@NWcXxMphoa@-|KiN^70$^_ zCU=sxW|GOBtYob#*YC#1Qw%8bLu~VAG0@{BO+mirL#T*9GD3H6-HymWJJO|L<&b^P z58T^YfFm)TBIedDh*h*8Mi~7dQhGJ8iX+K|28o<3q0+T6U<=}+5VTeTozXH~DR~gg ze;J&Tz#I@^!I_&EU>9Y*3xpbyZEm`47B$9#vAGLy#Z(bhz(4J zMd`Vm9Guo7=J3H&006O~yp*^G79g_8BBE%YnB-v#f;sQ`*@{kRFXl__ES+3YVBcrG zt}FzuXTyrUa^ezzwx*W{Q*dScM$&l|yjZm!0#4jaK*LDB1xB)LhU1igv}7)&=xe@W zaFBAQ)bxzvI0c6$iQ1UJ(HN_w8k&A7VUZ0H4>v;h7QXI!=u^-|w~;!7GlfaIS}0l2 z$nXshrc_5HA?dF5v2|xs92NX`48}>0Yy>W{wQObbInh~JOzVP~{9rmq9F26EpYqRC zukutd9?{u9k-h|eX-x~{% z))k7EgS#T2sRjR-40a(C&f7(VN}&U7!qpiFnLZPwldnS+x!as6t8-ib1kjWT0qIU@ zexM@Fh$k9sipa;*_kDBtX&W+y+LAO;U|X&W^8TU+Ps?qhT?Ee2b#+KnnCNuK(`fU88u4zswub%|8pOv z5)nY?Z{b3C_sAkfcP`vi!>jKgg5^IlR9lD7J;tB7jyU3r_e!WUjhPZBnd*V&h8@Ot zJcCb%w$C6EU$^c@AOW_*{1G^{h=kHA$-hJO&A-3T9G_iH#D+s+SrzjnU^rlQrhn{t zQPCz*LMd&^=C;sagw`{69S@4H0j1PhK5rs_8x_t^LkRo@w-$Px&%3D+Mb^^wcXi{7 z53WrM*BR@e@Q8~t0Mla-L@8#_)-MpVcP(f%Zhm08fdvQy+7_*tVmZ`fLhpY2u3^I~ zSl(-CP(wMhjNSq}tr>Vr` z?;4uKPAXATCYadxSUWARuq|G9DICyUnniFm`K@Y zl(M$Sf_gv1)_NKiY8|N%6GFQgn`j801WTID=r#}kIEknH=HcmkEq-5{NlYBfwZQ=j z$hxSMwa?0SZeVVJ9f>bv+i~lvM9WQ*EOW zJe6#b9BRFhlZyZgU7}v_%2L)y7}F2_+y=o)p$bg%$3ve2NnWKo1py0n708}iyCc!C z5t%MyMznQfZC2dpcLv%01RNJcXpIGqFTsu&RGU|yqDQq=c$q|@)6^9;^jJxee+TRR zbB2olnc=Vor(+B=gKWmb`T#|_*7uidVfym^qKfeG`Bk;eVz(@7>x9oZTA!#xHfDO;zZME`?&;+0v80@F)^Ig6N266UaQ34uEirzV7pg> zTs0T70NGHdloM<2EZx&iVRG$%N$Ivgi7}6Y!wI+dIG->^)BeUDi?a1vO*{1H+VGfD z#pjldBtF1kk_t;`OhuA>2SG7bl zRwUw=`&n+SwUE<-ijg!Wx@LOk0|ov1G7ZQm`L`vCA&fv^lkAF9+QE-0xr4oJ`N4+RV9XlGTgIabe|_s7r0d<4#>aEswFA@cZMtW@SHoQ+;_B ziHX-91(KM~7Nmlxl90Xm>26oZ_RH<2z$!C7pJmxvPw!soxV~JTKq9q}JXK^E1ghq7M}PP&y5fq5hB}i+2$zb&uWfm6VJSuq$sI z_)P%tophPdIRl?kJG7jfp z#RHb#pEz(;VhasoJa8!{|78Ncv{+vBI!~kmI`vaoDui?3x2oH3>))xjnye32WnGSl z9I)5Q_BhcTXW?xctOR1X*}4fpi7=d@r6EcxYsHziP(G15C|T5ENNIA0JDL$NFk2KE zsW+cy$;~TPQ3fV7MuuU~Btif*BK}J1UvBB^Kr5^g4TI6zKR+G#5>+#ScL_#!T7w$g%RD z5sCIX5s4gyd%d5lWmLU->XTn>2k$i4vr21~pUi1%zGb1v$AI+DvWZ97;*aV&;a(n{ zbJrqS2ICGK)_-ix6=#t?(2EYT{YCV**sNwH%JbU2_N(W&;+t^Ek$q;agnHQ7#aYA3 zbvP9ktRT-ApJSW1%|*kr9iwt$stZ`_qEP2Q{t|(9h4^wX3owN%4%i+V!?N)VR-z^J z2;&i;a&lm&BadTuENWzIiOp+~tZlzK`u%`pjn0KCM4(_ede0$8m{j?KP`a6zPYjou z&p0ABhJu(+Y_j+dQibBGsZPu+Nn)be_A9boepWz1kx;%5QJT;XTDdTBGciwhnT=b` zOwx2Z-$PRCL0k?pIoRvaBz|;>;ZBB|jo3i7Sfz1Q> zF)bIJSl3v&=X5V$?JHpB=;@@ovn=SNAJl!+W5MhYI5 zXP}$Q!U4s>A!-Y0!g)zhC!(Oj5yC<5O~B+u!!fTExK16ARl$9#_J%RnDOzcG+tSn> zZ76k3vV7t!-LK$aGSNOtD^avVvXB3bW^4Wu);FOXKBpM)$r6N;rs0`4FWSiSoEfS4 z6N#$a641UqKe0T;lo!|RKwg3CCxW`AB^4X-=jei|Hh>!VbbP3Bw?FC!n+-Mq{$SAaYl#4b!k(`#kyC z)Qq^D?kDjUHtXlYI%OorV=B;c5GT(n12=HQ3M6)-__^DOv9MA6G`O6}G*rgFLyd+n zts;WFzsJ9x1}&wUgXNrzyDU1_{AJz*yCeya29zA-UAvLv%$iRd;M}You*ta@-A*aa zwD^_O^mY}nDD-k$+Q~Tm{@5afaSy-{U^vqcu{^*#=zvmP-hA?+D#28F{qVPS%ViK+ ziM*rC1<$;x`n@%FP@15#HS{Xw|>b!qr3ZKd7EOFv7~Ll~oo+(?guTX?pg0ziPcbfA7k4X8(Oh zc;2GpIlGHiyw>RD7Ep*Vv%VaJi>hLaJ){Jvnm&F^G2rq&gH7tm5!*>Qe8IHuqP4jtuzB_aBwJywvDDA^oFpwfV7VZv zoZ=NI<*WPQF)8duV&i=wA<9WPoT7oZ>I`LEipkqdM>Rkq+51QYt)YrEMVQgFX-2Jl z1PC!qutl89sQ@hN*uYnx5l#u3Z&xK0nI)7F2nBWq&k6B9pYY*osakw~Dr4rV5_;&4 zVi9ioGh0w{ydW2T9IYRo;0q8Ot9IE*l3piTCs2#!&j1&8O-Szer#Fh+2+jlx1|2T> zMx<|?vV#(WOvR^sE=JnaEmB;XVzk}txgYApOTJofeWe=zR8Q|MnZJknF%(3s3+#*> zG6_;=v*0EnG)xYQoKeZGqYCGU96<=P6+Qo@%$XqlW)pWHS8j=Ajdx7{D#tnLsKoekGAT$1>Y1}2lDFZt9lk=nW3Qo?wtRcPIc%O2|l2=DlHw(|}% zlJw^oK*OK#slwvRxg^K*R+zh7>uN(&v7hXxQ#v>E(Kc;3q?YM3d z4=@FZmJz$=2^jTTF;bzt*uvX#(eqUd;dx(Sx4=$IERQAMk<{?lf1>3epnk1X9Of~< z^~Z}@I1F`|q5BeF%R}z^DWRu;BR|WqYAB+XoWz4jJ{q-{ZA{oZy*uxOUqy|Lj}I`< zI|G9imoC6pH_^zNHP9F-+z>?Xj%N>Fz zB)~+OBW;@tTKqg?p1PZq?BW*9U5J^%Ko-W9^i=swc6;K2cz>A}j4R1@TVQx_C={_& zKcbnQH_$PPg-_}hm3#qD{-9fORcG9O*-1!W9U;CTUlYCQx;OEUDQRIBCRXS1!>GOe zjQjC77efUj$-R&(b}N=uh`0Y)fLTt+UzmlH3qYsKsES6LWDDe~fM9&3h;cmSr)SeA zd{6;Ss>94$h+LiDULJlcIhMxIG@Z@iKIY13)RRE)xsD0%ogNdQQ5t)tTxgYy`0EM1 zD7iYUM8vmeJJ%ph*q&TfTa~nmqzP?cckP)vJ$Km1Jgd?)<*qIFR31esGqVXvZ&)6; zX90}Dp^F*?UAJ-U>SSB;?+rGpnB8ANIdQG2nCPU^d&I0h1S+D*e-TFd+f0{%xqqvS z;a-M9pZqY)Lt3NJO~h`MIE080YJB+|I6pkoYiM&Xe-QBb-T!XKL|f~UnX@0h6}(e| zrw;$Y#To}Dqvq>Ad7PdjR<6u#cn(&FlNTf2NOXDmDoLS9-mg}jDnFGln_dnB6$3TZ zg8`iy5YQgV^1U zcsM~fcy<~rPo5cZadmc@qAS4!?YP%YeJ>ck2XXLz&8O(Ud%hCAj=h(h1EtP)hjP%z z8ZfXXVqHF)4%z|iC4Hc)tch6ZZGd0#455SFXehc6-PMDC!$ zCk8h&-P1oPD=0he{-#2dTD_z)+3lgo)7@&!{ zaU+gh@{hzzXrNyn2_4G1D<{@Pc*iFEkfP)BwPv`AtUkn&#y)kSH( z1d=UR;ZDP0C6SLyG)|f^Px#X)!UKE9FueJ?8r|DrI1c}}-&X#Q#oKjzfSqfwrh6d4 zpM5n&sCM!2-yy3yG8YeyF`YO+gL1Hd>QzuIQa=1Uj2JnQ%`&MN?dlM?Ybiy9SEZMJ zbHE}~54pELZz10l|CXmhT*eH3EzEj^S6gFoR z5>FlJkCW54U<9NLZM(B@_a!9)D7B&a8tk@mB9pLyw7?z}DIZJ)ZB?jzLHa`VUx%>{6)k7p}ndjg61qSt@jU5U{NE*XfobV<026=A+_ zT=Q(WPsw+L-qEl%QS|37?*2&wa6LviZ_NU<5g}KHm(W%*MSrlWAJH|`mPdVaJgIAS5b5WH*A3v;wy;!; z6$3?g&1y}tnW*0BD={<$izzhrMDJIvut zRCe@3Nx*t~`pE8sIzC*&5AzT%W6U8)@ zgy9LjdO;=?(Xp(oKh}2I&8^gN9E+)wiL|HOVb|>z=U7ruN>C;}JOe!Q2aeN8MhT8{F!$(!?_e>x!Mo;kY3H6;WNZWGqteI-1mzM&YWgq7OqmRrh|f|)4}fy|#2vLm=R7TG8l zH(2EMec@qJXlW$sBQBa&s*Ap5n{c5f@B~|*quw8#CqFWIE+MzX7sDMFV8#XzVTpB} zpLE@&;YnnBeNAy}!Nkd)#lgE`7rHV`H04b5J1goP_UATrt}9yikM@FB=F>v%qsJZ> zNkV*sz_7!(B~D>72<86!nIh4sLK{QwgtX+OEKfXwj~=7kStzJ7%9L6~#mkfmPTM%J z+UTC)=}bPWcVb*7QbuDx@-#m-kmxmBQ9>cEWFt}prGf0|G=jat(C@B{Y+hwY_i75lmVmU{gu^O9B0e_FgI@ZR~ z3FWPhzPhj`e9)3*(WrW{5uxwJw9)qh0#TKOX7H#!Q~arg)s~Gc(oqeVi>NX!J4*s6 z-Dv$*9GQ0tDa@tKpeoZ@n(FRyXO}A)Kr#sJr=#6!jd>P;O@r{4I%>gX$XZz7403>aJdfv}_a~(ZX{!;5 zx!qtIP1^F;g_%>Yc#^HIUohMw*CvZKGCGqGw9rDK!89_z?mD2yh<@1E&(p|JIz;(dHq5psU zUqP!A0{Q=OefI#K{XuNDSkxqGHXgst)n$lDq4xZo%?#veOpiu{>%mxY5nvCXp;|{h zjzim4n3b2amiTpnwvLGEqvY>nT0}kth5$J|dwM=VU^zaM0BLbwheC$p~JCwnKe z8d>xNl;Aq{&un&t!t#9_nE}~*XZJUyGBN&z_e+&gF-FP83<_7YDp~g?{fTJE>@0TM z5yZU~>llgqDj zX!&vBbGEx#Mx2G94OE+n2L~ej@Cb2XH~y|iohyTQ`yV`yQ%nzCHy}O%%y7nd$X$;G zR+}C?op7t=5W}!@=_S5xceB-S@K+ps2e@WFp@4Hg5U<$_StB9Dmw?c<{_iMm*SD)R zBftQy2L;2eaIj9Rnl)S2#vCk`%z~Pa*qoZ zKwV-^>RRDh#whCu1@!F*fE3Sn@T=hqPSYq{jVtL$sfd3cliC;XK7vY zEk%nh1cnbL?>phDAf&$%Sp1m_<1b*)@|B5$T$H#xcqiX&bHc25$Am!E(?@wZ-J zJEP7AM{aItPikJyj1aPYk-O}#rJ0jlAD3M5bJnu@&WxM-!o1&6R<+G`_1%qOLg3Lx zIfbQ;0ad8KtVOGv?Z6v)r^bk>_j|f4I@ilxaT2eR1_)bXp?>Ljpv~vAR%Q=3U&WNm zd;X_X_T|N7d$9vQwAGB7{yq1eys!8p3)KO!t+5Q0c%bt1FwLsSahcnKgH>Si@0IV0 z9Ncc$s|-a|8wgZq5Y%!wf66nVB^B6H8U;Jo!QeUs_hKZtHuB#o^d6_bwbvoW%OvgJ z@M*~d;GR348iu-6%w7Z)6cjR&;}T)IXi0bJS2+7yaVIt24F8DS-X`S0Pkq{)(|_gx z{G)C>bnTKeF9yJ8&7Do8{edSz=&Re)$YdBOJ&T5qmY}SX2veDyhbqx&%K68nOLBw# z_3y)^z|F7~zej?RF}-Z5XA{h?*HTw!LW%COfJPi#iE`Oc7TgC{>uo4bE#rYiT8%*j zn^-0OGqU@ejA(W?f}FX^;pOxewKfFvuZ7};C4wQb&0m#n%URHq_6teFL{&`SPwnWr zOuSPJ5bs*kTiq;mRs815Xuwhwp4IR9OAig=W6R(m4NhTB86-)J@t zg1d{|Jv`A?Vn^VK`O|c`HCOo|HZGd>nyH6KGPcGbKL70c`X*KS@T>8uGBwcRxtp3z zi6q^3oV|#T&n~x9WKaunEH(=_&s%uZ7iW<%tV^DTe|oZ3IM7|KBpK#$S-2vR_*U+x zAlh*rehZ5w?OV$By34RTd&nE)|?vGPowsxSbep-Z#ysqn%;e9_!7w*=3a#qd5hQ_00%~m0)1byij9tt9Y zo~_145|*Z2NusYQ8_oK1QPv52v7>6CZ>RoH=cBkya z>1QQ%J;n-9hSGQXG#a66TT*vAA)!KA z-SnH)I#SYn>q+b|P{w1xiKKSfHTt-g`F0@o7({u#+Jf+k1$xJBjHx{yDY%C@u__X( zV-6qgj75LBuJ{b?C7jUvLhYA+xU8F2^KXk~rR4yH&2jRKyy>7w8Sd;py&CnsiO>J) zE4eY%nt|QZg4Km#qtzLb$*`4QfmmW^5+hs9Km5L8p{JacJl9`!Ph8us!8rkMa)R0u z=-rfP#q(!pIZs69`#9zri#UVBb3U79iX#m%z73t1b$V+Zl>=q12C||XB`%2150pAE z#(Be&e+_i}ur5)BCHK>H0aK>yddIoy6i=`u9ecN$yPikrU3^7?AkZbcG6{qzu7qjU zo7>ac87$d~lgVC?Tn%mnz36~eqlv#+T8M5Rp_#l0sHdC@R#2{n3He4(`Yh<$Zz|Ts z2t^GJoR_cY#rc*J?k?+}t~-y$ni-EaW>^ZkHnb-+?!uMYIS5~WNbyXKI;0j8RSioS5x&JQMsUP`fq%xjhR zd>yV!EVF1Q=*X9cSMS6a+j&SAkZYK@s3WZ;Zz_IFu`yG$PckIxbt>vRl&H8aS{CVB zO{qz5%5qWscncUcM*r8whLCZUK?k}oSW?$R@aM0~I^7&e4L+ZNrn>?{ZHemt|CyiYc4ZezTs(cBHB7EMh|#*rSIKR}+xP;UkFU^bSw z0qC8Hxr;FtK&R)A@$H*dC#PzbfzD6FZ#4Ir!fwAg3bXqWtJK!53>83dD6d4R7`v66 zh2xG&rDg$4*zU^*I#ATB7*_o1FXjw_Za%(qSi^2BPWU6BG-X3Ble*4Q7fk(T=6!DecRGj5gVb9k^PJRw<4 z@^!u(9n$6JHYX-b88jZ1GtK+F;{Pl&5!lgHwtfN{ISnSxpt>fQcW*`3-gkMmS^cm6 z=HmMZ1`f-o-vY&qaWY)U#MsunM)B=3p!#B=g|tF#2RS>IgKE}m3P>2hRH&UYmB=~i z@}!SMY7C5Gu8>fs1kfLt%G{>7XN2y#4kb5HBHBI6CXv}W(H(2svS{R>b2v1Mmxq;w zq-mEyO(h%IKictQ`m(m!-($^wf$Q_9_8JqwBA>ol{Rqg5;#067Tx!ano@5>MxP9wu zB{)Vgg3WA!70Z$sT%OJ!oKhD-ptnDwjeBxRptPC5S5mG*;~VLNQ~usPJBRiKF@Q2| z=Cyq3{5*$|`?6KQr81-Ttrk2~%y;qo?TkgPXE=M8a7cFWAV#HD=j>PH>*v+2Z4>S8 zT;a-{sXBC)X|xxlFT`iyF*-=})N~EuPMP~U;}u!Twbasg5%rrEJi&s#y|f2i`P947 z{e7_?f|jC27*1<${(MtwN9p>2G_tJqC0rkvT7!*Hu=jbopfWwRtjsFhvuUl@!H3>f zxx|d#Va{TGDh%&5x@N*_^aC8_HxM?~c&K!bH_DgpZg47>FBf7MJAVT;rrP<*Naa;_ zXGnCAoRlLy{c!;njf&_~GRHYyymY_|d%3B(eGaC&iYvofny=PjepueHRg1QviUZMX zHap_;3Zt=a=a(FWp}>#_-V24ary39VOO&L|t;w=oAbhslPB+p`(<>aEk#NRHCQ}jr zD28kldl8Ihc**GVG=PzA@nW&z?z0F-4%Dn3XBT%3d#T+*dLvo4>ZMjyF#fYnBkTTN z#!_T-W>j#EX)cO0t4y(rh3`o}(+~NQI6g|XQ#jjEpK2!pJyP$K287q+=cXjAQQqCt z%R%ibbLKo{bmxOAK#H=-&)vaS+P~lajxSx^8Zj1O9Y8AKfVS;Z$MpOYq56_|;#y^D zUS~dRlM5IG@Cd)&&KO6k_B~*3QcOJbxA+3)b+c2ihBqCR<&SaoKX73U#3{07fTA6q zG#cO7UOcnHeiA&y%N8l095Fm zrn;!Z_9L9vhtFk{j9*D`CZgsXlrZhj6=mCO#U1_4f+Ts97t}d!;|Aq`{<7a! zu#Sey+E@gkC}3B~%@brJvqY$&O%6sA?r1CHlV+d};$~3GcTeJ~pZCguyG%i67OOoR zvDAM@^Veo!Pn4v_5hA--{&YW~sq5WKWuYUD5&+585GG9<($%n9tW1NGTp1=*x#$#) zJZ&KX*j}JJW}g>bLwyrwSQI$-d#Cl$2M|0On^Z8ALc`%j%ne&NXY8(untoiMh&<+# zNxbf|;g$2LAxH*r^VD7){{>9&cqFvW_R5;4*tcwE6-LwZ2 zLr{=0<1bZN-FC_f#sL-EBfVK>34z+Rl)XHHy(xsD>HcbnO1i{oI_T&I!PTDiIrR14 z5*4?^lI&*#hJ`|CXg3$C0t~O~pnXHrAcU4Dp?Bu6Nrg?6MGbjY@;z*-LnD9S$+je| zBWDtrQh^R+3&Zx*M0(s)y6g1n%sf0{=7hBadZJ0Cq_g-rN54$$pbB$i{-CWDHVZr} z3fJd2W#U|EjQQ9D{mwT8a`m>kRTs&oS<}W{FRZVqHkP8sngGK448BTywJj+7AVKDh z)H6xiMX;@)xze4r{}azs3@w_-hF9v`S1T)+iSt}iPY|uy>Abl2MyTKLfB=Q^aQ-m7eGgms{2o@j)l?-GkV!}isstkl1~D6aIt(RuSi z0Qy=iC?b8ROuL{5A&9otArZUf0)F(CuH)fR>%p%ihFz=1(FX0HU8nR`&u85a7qt@5 zrG4E8^!+19HABCd!htu-e_P-T^}J_%ktNpMXA4@G!&^S`S{f_qo$C0x1_{U5U z4GMfW@o{MS*Hw*LW;TUME!Uu5LbF_=w^J68V8*o}l4}{JLuh_DAy4L@10p@4KSZLV zh?PL~S>ic4t$Icr%tC2k{h&VwyE*0B&tW@6?A;cC=HV8c!VNn>4)<^_^Yszgxweui z`V+_6W(9KeIuKh{58S`~9HmeNbmr@mdV|C~ucg<~g@eA;Hpy_F;!Vy0i?9{Pax9 zuslwQ(|U^LB*ttWRQ*jM*DQIx5eF_Bl=tD0j+*yfaa0mdjwn$x=E>aGPTgePvL6$o zSvXu~3&9Hc!|XLc0XWqLs%WuGrqT-ChZ4~0qGf$;!iBRe4nBP*aH)Vd4FOH-dNU8D&t_Q}ddN_f5}hA@6iH`LGF4pHli(Vs%WQ_|K5J zCVw4ie~KrGc-0G4%l-?LshNLW+LI~MXn`aV?YipXm84|P!>h#R)@?&2ikFA#%L_8Iz~o4vInn`CKsD0 zu`2xnov;96qn<)0fgTbNlruKnCbS2`xj{cX_BfGPc~?$t#C%NK5V53`EhwvYc&g*0JfIzOWyI>Q~e17p!6or!NwK>*+`{t2c>A~+-bPVNEbbTk13DR@8OG;meEl_Hcw zprsFow<@@3tv4*7;JDkGgA?s3H@(SF!#}bvn+0E#0qavo?cnzk!T=2_)S);hVMV?@ zHso?dB^HN-MA7Bwrm0?_m@f5`+Ju*cwHAJFFI@w8Ah7ImYWB0{kU&op7iv#^*>Tz% z6C;`117WW@;k9lR_LY0jWY1nFvFp@Ic?yeqGCvEz+Bxg>3_uEU2%7j4V}yz|H&!}n znW6O4(!IyD=~L_j=$6jPF!sdb!OjDpfy1nzhM6vc=gbGOlCP0a%;1W`w770bDkByf z?Jf_gcp}vc_iyjbmn5^oRxGkpt^gYazPM^o-sLe-R6v%8+O017#=U$NTas=C#U>6C z;=G(UTB%P+q8Xm@NNqxg-pflg7>8~>MN8BbMvVO~k4PyJL&!8cOn+D)$of6G?ThDX zziD>tm=*AGUeFnNdH0VTLdP3!;pXyk@RW$+CqvJzkyLWZ6vX>lUEnYFMvJUGGXVkh zoZSQ~!Z|dA9egTy1kp0x@S63Gz%V1X-9VnU`vD29Hkk0GJj$OjeGkfmq**KNex;zE z>Z$Mk5X>6^MHau2wF6p@j&^q_K|lI)yrZumSu(zYu8Bh0VrV+uue_eD7+{X6Y5jU7 z4iBwdzIslXtv)?CSH)JW9^!F^Zk)LW= zv#pJ;^)T50lqcv5o$CYo282Xpd(Vn=Ar%zUgf{1aPG+bPE}mz^OI5J@Vs)gN>tnu5-Y=B)faycJF&=6gT1qST)VYr`$n2zp9}TLPI} zx56iNN@2r2Q1Eqj#oW!*jBCu)pAwuKlT)+m8rttFD)%GTGe(V$n(TGra!k&~L)W%u zcjB_Udi?tXkb4hF1=U2}j<#=xWzmx3L|jVNke)D^kY3CDL$fr!)LxD|Z^)rzzVg06 z8^H*^;3?pN&sf3Z%I+ftP8V!yu-WbBzt!$)@=mY@d}tz1*8PiiQuzNV!)d$5z4R&l znuO{SA(GAKJ+d}AbyTUV?}&N&CBRPPpVwYQRt&F(ZFV0VOJz*cC@%j{K`F|hK3PQV z-K*Dx1h-Vj)?yqx{O=jrJ&Co`+RBri=1o_hXKTiYbLZ~)kIWs70lUL$o2O)p&*8z% zK$QEomTAkGsMBvBG~_Phjdv-}%Reef=o>#EYra<={IRf-SXy9-wk0bi6J>)@J|PWr z6cmru-ZHZ=3>;>vKbyPwMe_M{TsX!}oRB?WQ2UT|HJys)rj zx*p>b3^+xISKR(;W|On;Hd)0gl!r|HJS=Z75IP!)j|^Md8>7uU=b#nM)Z;ay_;XY- zzCWIN(bGt1^;*gIGHHRJ`|=CPo^)cMr}upR(4KYk_P4WRhC{(?zi?ctX!Bdm&A%74 z6nM13#qL!Y^B+G=Mji{S5zW+%aS?^VmW27hQg8w@PHLCUO;i7}4uLvm3J;sGde10P z+88o=$hY9mIQnIX`VT6pLKOd*0g_rAR(cCt!PZidsgc`sU6d+RRAGG1)O=a`DccIS zD%r55^k=C$3z94~*^m@n>(jHzjy607{6I81)nj1v-h&9gBhgE^j6{%XAqE&e$RofE zUYbx&fXZL@nC!~(S3if%u7y8H5Epr+6x}HPO1y%YFx4St^J~ZMN!^I{c10U{>dWLp zEi5{=5yZW`@v{B->}EI&J$dtKEq~wL-n(M$b!plw3c@n6K_m+L^-4th{Z}6(s8SwN z-MQeph)94opv8`X!`{lk08wvbTtPRND>LH3_h7!i;BIrCj0!-5Fe;9)0SZ5OOdj=VF?*(8& zEM0VSxUQqd>4*w{N_m?Q$|$aL>zgGwqJrE;eI{MU;$0^Gl={*u;4U%gvl0_StiM)2?%V?vm_F6(*rb#`;y2Iz1o?TH^Wp_57|Tr~PH|5&`6v17YK-9juq z#Z7qf&6Q;#YDUZ()E7Q!<;yUezTvkV7B^XA_{UrQsUtO0|6i2d1pT4?Zn3zr&c2$E z&}*Kyk;aBsfA$S$jz{k64Rc&l*fmCt5o&Yw7=4`A_q4rF>66=v2!>i%j6`^+tCg^y z4W#tQ#kv`>?Pvozc+7k0V^abqQ8wHbvx1i3);az;u^BC^(k2Mx7jJ!_99&YLb^btH zSa&JK4mA-S<8qTSTRG}!)h!Y)rv?!By+V0L1TgwE$|d-XG^r)&OeXnmV`h|1#R~HU z?tGZ_@J{LAf7}GK{OvqH`Lo~oV;Oe8@UU-Fp){Oz=nZ*tMa%ETH8q*nxUuc^6n#^F zBPc9nw1Z$sc;R%9Xs+Et?1~6Va;#~W?Q?736%Z;*H!kW7)2bk{=v#A5k4II88!5Dz z&Z14m>dd#@RevvkH0fDyn_sCaz?d!U+d3vUGNDAnC3poL0o?CA}wkBy3H-zx1E zF``Lt5cwtEZ`CxUVnbB%M&4z~i(`Ooq7how*hp=R5Y0QX!@~QvwxLePeVOwJPe=N# zwA$m({YAr$CW9#0%VH5X`==HaQ5}-rQE3ZeR)Vi-q=qTZVlp>7j#wV%vTf*O12~9NadftFtn6CYrab(CE>zLbGI8Rt3;g6$ zpm7|vTd2NX-VrZ2eG)3yZ{Vbi+AY00YtgS}lNtS@S+IZNu+JRSbC;0H9=phZP+X!> zqbnOLEix~kK}M{+0fr(J^WG^}pBJAL^{EkRzN{8_%;fv(Mt=Lg-f)=w<1W(ID`1fM z`CFk+_Ys(tPurgD-<0>|6tlSQWUn(D&vOgc$&AF7g14`in6Og?G|L+QMIR)74u~Bp zYoj@X*N+#m&D(1Q@l^8-Fy^wedLl|)V2Y|n2I%rQDpOlHju5QjXUXdhdW|P*!JZQr zl`#{Vds0{2r_ZF`u$j%(q{Uui7Ax7BJ%-{>iVQ0&_Ufu2+zYMlQqw8>b)btGs=kds z?b43)>n|q%cxhD_eZN~#z)8%pQQrS(zLVdt=CxDoTYao_1p*j>B1Enox5*lNEeE*3 z=;0`q!RY7h4^0yVf!k?8Sp0ry13Gr8Ig{r+{sX8kiVa7rz~@Ji9~2vonRL@E=LhPt zBu0z`a&dD@2v)6{yIt#z#y`n-*3EiZz3b-U4_GQmmRW?4qF=|8)Hic+(?;1fFT?62 z4i|9P-Le3XKxkuk{eDP3E%O?F-T1fj;bfnAk7L0DJ-J!e@cP0lQtdOC+;*)-jSKYo z()G&!{{Y`WAis~pg}{Tv@$i@k8)IfYMHMr|4|O9lG5JEF`9N=8b=WuQtr8A9}SLTbdI+Gt#zC${qF(f&g7G|_0~}~&u~L~){$o!!&D1w)##i` zt;@%7lsN)8jsilEQ>DDfYckL7mWk;doC$}?|1!MB`+vUSit^?A@YRS#Sv3O}?buxY zx372}hW~TrS3kQS8OEW?PYK%bzy*N<7t!F`eI`TG#<5`uKC7%IHB6Ks>Z}Cc^9!Mw zvoVxbwOh{Y(;QXJ%+B@V0U(fbKSRvD0wkBcuMYv4X?M^)*Q9}v^I{z_#?#J7EV46} z1S--Ny6o5R^pO)mD9KOiur&x6;i*Xc;L^Tp4-Uj(U0e{3A1|*sdvp1jH$87L`IYyz z?JmIAn1Ay1SLk-29LJTw*y5UXy~UV|g2yb4i>uZ+5yG*}CB~X6n@k1k2?-=)-8G0A z(}Wqa86sY*2akAcRAj)=`KinExdP}nmWvFw=!YipurpZ}pxKIdPSsZTexL`_87*iR+ZxTBXVr6B0D4X4XyG#* zXTN6~5!Q+uag}NX|2W7yufSz^!&GH^YA-!>pwzK1dY~tM^~rzbj`iiIzT%2<-9=}9 z@^fN8`oy7f$3y$ejrTlIK6~H8<*r8_EBEbxqCE2Cp>p8R;c^&@0T%^!g%f|<=8a|7 z*3IRdo!iTWdv=z~&e>D0y6~LxqKnTf7w+9vc5aEcy1PWqox5_+w(=9NyQ2J^cimKO ze*8F&CLXpcECM5~iP6M_;ut1CoAY3pfHdLig)6Yqhk?G$$2P{xjuA&EaGH`+VyjE? zV;I&Y8oL>MHBY&p&jO&1pmXXU9{|QHjnS{1FLlNp9ri5rH4G-5R_P3igf-P5p$NZ9 zhnpHmee%Nrx)nd=_QS8bq6e1&xwYQ;tq1dPlDa`soTptKl!SPK# z$Fm(<1iC;^2uoHsWi_30?--{920(c2SZmaLx!jMeY11(dHtBAF@`o@0bt_r^Xu=z7ka+; zOZLtE9{MEC)_?W6yUNf1>0g!K`^Zh@{sVEJya|7b0cY*95tr=TxCpH0hBaST09*j# z7!!?rxG$XiTmRuo#m9>&=aw(e+2`IO!0{x| z1+wR&RiktaH>MkPhLYG+_+h%4Mk z#nQ8hsZ#RBXPS9UdLCfJl12>6cv}62i?){^e(hyA;bM}_vGCsh=iYro`K9-KwA{7- zN&M;}Cj4&v{NiSOm3$MoSO7Tr*LmV|g2Y+V3qY@p>=zZ$M=t_i2)GCw!6I|yU^#sF zVEMCK?kP8X?sv;KeCX5V2mi+F%d4)O{->*R^Y-oBQhw;wmy}Pv>*n$(ZnJa_3)B;Nk42U`-CEbo%)VG>Xrak2FH0NfHN=_fO6=Ga`4dO<<~!SQ~40u^22X^efiGU zy}WGMIHyAk&H9?>om2kS^B*cd^XZ3hb%TECY>oB}ZwGX^VCPBB{fek?K#q3oDASR*li9qD~dIB|xSUd%{?hr=^?ED5=fdiBZZbOSy`Y zd&z_?Ow}e|$B0f^HxPS%VN(#`>Ee1c$o8cn$0Ig$I^b=mo>0=UEhaxE$EM}uB@80?T@>B2n%kt16oB?;>wL;`Nid3w>?rmkDn}WS2V-%RNWjr_7_y$<``N9MQ;(Hp7y}gfmjy#f?94tvW~#6 zR4Dh^**w&aWlDwkpoTVk7keshP76S4u@1J7N!%&2kQ*}Tg=vO0bTwl$Z`Z6NuZd2Y z09n^~0E{1<{Iqk!B7jT(ue)ql`McNdbI{4@oew`&{>R_=!}6S`XpSlfad`$QqxXRd$GyfL+b|laGe7diDd-TCk4;oI4uX zPY`{?M#hEw5DS?&UV`(%A~!BTxH>rg_#@@#-}ecH`ZsTTbJ;tGD*?W=^qnuhu>9JM z50qPRCA7>d9*q^-%(lAy(RM8kp|?pQcBCwV2EJ+{QeW4_wo`ytAg*o&^N9NNJw}48 zNrkMNjx`cTlRfGo&j(?uH%N;C zJudzE)c@@-KCfJNF@MT^`ohWo4}RhIF!^t<6Mr|({CwEQvp*mBZNTKipIy+T=ENRu zJdCBoaFgoxz`9IfZ?_J_^3e_Kda|Bz)FqjV53d4vE3ymi+H-C>xpjB>#rJ=z{P^$w zdAxrxeO|6PXGi&_EAjU;_?mDYBaW5E5Oub(G(T)dIyP+5_*T4!x;OsDnZ}_aG4oW6 z$wNOk!Fth9y8Uib5A*beIV}Ke7$(P9$7XbWMPG^zHf3X~VIT$?ga&NQK9HN9Fxx28rXqd(xw0L@^XC1=exh;;<@IQQfN#(ZmbWy3Uw52{Z=0+6YeY`rsRmzj=x0HYVj`x=j;LXH&lxxr1gdd-L?Ex@t@MjA4}-rY0m`q;fWnKy%q)#O6?<@5_22BlT7Z z3L~r4vw-Nll5R&CqhaAM5_V?L_)O(Nn_YQ85K4uZN{u5mRyxXoGZi5Dw^&#NjvXu4 zowu$0%@Rz3b56$L*lP0w$X_5t! z%qG(3R9l5rT#mhppBALSBCzYMa@&EU&>1@A#_CNOO>XP%J=ij5d=*703=Owi5cczOG^7nbw3<00I{Se_gvXHEH~i$U&(Ix{@dC$1#`s|j%Z?))n*$#% zQoIt_hQ$k4FYmhXuJT(qe2R^oyu9wxv&%mG%93vb+Ss+4IF?a-99T}YyPS`)Pd2eL zz6m#DvvbAhNZuyuwbdQ$G(6lUD=A?s#%xUhBc3!i zDikB>WQ%7R#+l-h^Ht|=EpK@~{&xGsh4=kG_IvLw58~NYo&31$-;9TBe49^`EHWp8 zT};H@SwBz8u(wGqnG>AD-}(3L3?5tar%b=>6TITkg>uB^tH)chfMM}Ej9Y=9`}2>L zyB|FO(6r^!-P_8m@fV168&C%}D)5*>)Yw`LJ&VUuKAvW_2|!TYn!jTv99gEu@l4&8 z2vK7Nj<#M*>p`2J9W$2p=?ag4Ih5RRgr}$yddWHA2`?~YC6P`72OZ!th6B(__|L>5 zAjQxCgsfPJZ#cR{Jii5qv;PLXhWfS_@$5hC8-FKob@8)*@>k^pci=5If7Cae{Ol_y zT5s|~_QdmKZ1$M6I!cWr9orJtR{=d7s&yPw+g+a^i0x+r+b}tI?kOL=@3HbbAHI>+ zNy`?za((^2J@^U$9t2`+x?{)Ha9mL|-j%J#LGUr`(#`PUD=2u2#-W?dFTyoqOj9Jr zai|*dSsvO`h$-0lECBAfI$|N3Yn|1SVau|0R7xKT>!ow|Ay{q`HPt1b0A#!Lsoqu> zePL|a@Xb1W?03!XjpggFn*Qv6!>xCgUwGdq%QBzx^WLAA(K_?T#GILIJOX2r%_4L| zY?Il?WN-SBSUGm{Vd&(aF-;%s<);)Iu}I=&rQ;j6lwbbfXUYQy@V$kJ%d0QiTlU}r zsXhltW9D%sWf8$H#ExkSg9O*kCezN+x%Yq>uo}Ngz3agLwODOxeUA=}Ah(cPa;Zwg-v#xVQ~5XRy=sRbT=+r0Nz)?i%TE7Z-4od&)mieCoRuEdq=rw8&&}P{8}ALgx8qnYN+7Y zQkRX^C4CP=!FW?*S!~PtfzD#X+RwBBsOUmgX|DVEECBA0s0H`Tl={qD9_p+g#<85J zpxPlw(v!Ek=?Mu;p770XAJTMLiO-wQ!!y5cyyk*B2ie?-%3s`gJ3jKeO%sK0`z>w6 z2i$&Xhjn;fn&AY?6SH9q*~9KS?WByH=C zau|Ol?zca3Gk%tg4>+bPyYU9*i_gZ@60XkDU`GWp_(8f_J;u}|KI3$3*ds9ccjtZ7ANX(#WopL{)1;8C}OW9%Rr~t2y1yACV6JwodbAXij z5Sz-3X@*mW&8A^p($k(c;c1AC3jsg+!vm+6oQE^?goP907vKBw^5}6)BEC_Fck7q+ zk`E^zD~icQs!2yx;sr^Vh9f52n@-?RhOtfBut_$=0ZcOnI;lxx%k?NuTm|s^0(c(q zzT56EH{bUNgG^So;@gK;<0?R(1n4=yDMEW#2_vu47)ao=7>GvLXBXmzSjowdSi6nV z=0|J&3A(&~jQTtc<$M-^)>-wYCTDEI8E2}FWFO@q{DXIAdp^l#eX9?O2+7H<&r@k* za%G^s$`u!~R0Ez5|M23^Tdq8>Y{%!%Qhe6ijJ1)og$p&?n~TQS3JorVOvA;;0<7I<@98+O4_(c#NQps7F;DHo zy5vMh{9`Npz?}MN%X}69w~-xbouRTRj0if^%PC=!%w+ZwN?7;{7QA(i5jRIJcYgYI-6QL%zs~+R1auUbq76ETsWeY2!OY-54_|^BF5wwZ8{LDiz%HJB zRd?VN!oCcgc#1ta?9}lpfZtri!_AM~yT9CnUnicjT#9ko#;+=KtX$L{2p(taO?^zr zZh=PgK`q*pW$B=>j?~8uZOtH|io)6<^diu~m&cyI-rQo1VYA;;f%l|iC zehz-^1|MxrSpMYGx0Tx-!)vm8&aV@M6Ger|ip_az6BQQlHFM~K?7AqI3tAkxh9PV% zq?i?U#xekT1q!U>q>zkV#*tS}NyA1~1^tRo1nxiZc=@sa_kHDsc$fbq&)83;cu|5c ze-B_ko}U~(f?q4*vxdZ5t2Fka78c&Zebu{UvxOf5O7c;6M1}=gaZ+I5YCV<*U9r zh|n?il|_^?87tYcs;ig#M1 zuL|sS8?dDuMSp+kgLo+jKPje5_SOcsB|Io9q~iw7I<|><+lq&$XJ3eSCyY%ow5AU9 zVP2WIa!@sE=r3jGE-~ve-@(SY5p2$JO~SbA)6mXk0ch=EpL#hKs;SV@#QIE45CAn7PC{dn5uAytG8A4dJ*x|A7B)RJMwHpWxF=R*6IpB zg0w&;A7FSRSFeDHi#Uy8;HI>3GCH3Hpf#9{kHWM>dSF-VGXTypg2Qq!QX0q#f8)U;t&6r#|J)lZ#l7q16F5$U;d}AGX>gm zF4%=;0Baj)<1+?*&_PN&^(@qZX!1x=b+l72AQ^1U2aIgAXMGi^Rbfoy6pum#(VKw~ z^-D%r2=u@Xc8vw}_EVt2E`?P*_f-@|p80ttp!X-hr)me0su=cGrI~1|+tUB7K}Q1E zcrxS%enz&w8ApQ`0N1}N!2M`hfubE~VQd(7iS|L)WFP87mTiDn zT{To4jR28o@{6gw2Eukwv9=RJU2HVsQg!dfrSg*Vr(FOZdi-Gd@SP9FWWXYz*LvAr zB!l_j#%B3Ir$Tz}Sc3L2p*KW*?Vz=*4;NMV`@yPBdk2@GR4dEnI3hu}U7 zN*x=3B6G+AO$GzHoK@rG`?)Lt(Z$Hq@Qga>LmxaaLhL1HM3x6Y4HwK%o{b#A2*f6Q z@GThHj?4dLykCCBIa|twyKs*=VYvxEpMCcecxt@`zxKnkmJbf)BogEN=zwPBNw2dA zWU3m@d{QKq5meM)3z-^h0A=TeILZSICPhVKuf@wWTn*RaKphm;L6pFSKsxSfG?{w4 zaB4WzoA_SSs1JCf4PZkAZ=&m^f_yVnphRP+%J!_U@VXzz}@&b*JgLJb|dyVoZPXLD?3cxiyBNXIzV(CWZh2KmbWZK~$Z|A)Cri26DA+ zgy%M-uyCxt!g802{d#!YBVdbb22_(DIGD^{G?0?$xyU7S;ZwW5r2`K#XD);fZhSrF!J+VfZy%0)wTc(^RhN$g{qn z3NY<%z6*dF9t~Fi(GeeXty35Pj704=u?ZvI{*efdnhJ4dgQ3Z~Fg2O=;eYp*qJh+R zJnbH`dij5{;LrV)%l1yY0PH__q}1A}_o*nWs^ZBtVrH~Th3 zck;HEoQNZ);v|KO_^faqMGXR=<*Ww?K>@&%x_}>3!|YIuE|0tz*9pB3^BrO>oLiNs zSj!Q)O;qT~YeW3t>-m8`V;kEMdizl(Z@nmSRZ|(;CDk2Orz$xa?Zj1&oKv~3Xz#@w zLlKZbgRvU(csjcITmi7r8kFdZlI@PIl=;-@)9Fz!L2Hc>I5o*W5~Akd8T-VEa^arM zlYjm9jz zm-+En%c+au@Y1wnfzA$KEaYU@OF6?>hBlf2_N6VU8Iv_xNmG@praL#I#%L1zt8nOZ z#bPf8-Z_Bca%X!}1Tz2+#D1_avL3RnI5w2b@tn$h763L@2S&8o2a!7&{b8DQ1~b`mxeoF@Br}q9ox#54g8pHx^g!z z|Bs$Tf3N`f7KnXjA9b0^=H(*eu>ZJ#6ArsP5#(2+)yrgps+{}Wy6+fKUmX()^np?K zFp?;DNfsvJ%O(6Wr17vR*@5r1%M-7GD>Dpd*XA2|byK^30CvGXpz4lxgvBxF5J}$! zY09b^h#k({05A}H`OCQ^P8)VTpPt}KCZY3N0NA|N?%biKtY(X*^2@>?&M@u_9=