mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-12-12 10:37:02 +00:00
Merge branch 'refs/heads/main' into gamma
This commit is contained in:
commit
40cbff5360
19 changed files with 281 additions and 63 deletions
12
.github/workflows/build.yml
vendored
12
.github/workflows/build.yml
vendored
|
|
@ -169,12 +169,24 @@ jobs:
|
||||||
- name: Prepare artifact
|
- name: Prepare artifact
|
||||||
run: Rename-Item bin/Cemu_release.exe Cemu.exe
|
run: Rename-Item bin/Cemu_release.exe Cemu.exe
|
||||||
|
|
||||||
|
- name: Build NSIS Installer
|
||||||
|
shell: cmd
|
||||||
|
run: |
|
||||||
|
cd src\resource
|
||||||
|
makensis /DPRODUCT_VERSION=${{ inputs.next_version_major }}.${{ inputs.next_version_minor }} installer.nsi
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: cemu-bin-windows-x64
|
name: cemu-bin-windows-x64
|
||||||
path: ./bin/Cemu.exe
|
path: ./bin/Cemu.exe
|
||||||
|
|
||||||
|
- name: Upload NSIS Installer
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: cemu-installer-windows-x64
|
||||||
|
path: ./src/resource/cemu-${{ inputs.next_version_major }}.${{ inputs.next_version_minor }}-windows-x64-installer.exe
|
||||||
|
|
||||||
build-macos:
|
build-macos:
|
||||||
runs-on: macos-14
|
runs-on: macos-14
|
||||||
strategy:
|
strategy:
|
||||||
|
|
|
||||||
8
.github/workflows/deploy_release.yml
vendored
8
.github/workflows/deploy_release.yml
vendored
|
|
@ -93,6 +93,11 @@ jobs:
|
||||||
name: cemu-bin-windows-x64
|
name: cemu-bin-windows-x64
|
||||||
path: cemu-bin-windows-x64
|
path: cemu-bin-windows-x64
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: cemu-installer-windows-x64
|
||||||
|
path: cemu-installer-windows-x64
|
||||||
|
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
pattern: cemu-bin-macos*
|
pattern: cemu-bin-macos*
|
||||||
|
|
@ -120,6 +125,9 @@ jobs:
|
||||||
zip -9 -r upload/cemu-${{ env.CEMU_VERSION }}-windows-x64.zip ${{ env.CEMU_FOLDER_NAME }}
|
zip -9 -r upload/cemu-${{ env.CEMU_VERSION }}-windows-x64.zip ${{ env.CEMU_FOLDER_NAME }}
|
||||||
rm -r ./${{ env.CEMU_FOLDER_NAME }}
|
rm -r ./${{ env.CEMU_FOLDER_NAME }}
|
||||||
|
|
||||||
|
- name: Create release from windows-installer
|
||||||
|
run: cp cemu-installer-windows-x64/cemu-${{ env.CEMU_VERSION }}-windows-x64-installer.exe upload/cemu-${{ env.CEMU_VERSION }}-windows-x64-installer.exe
|
||||||
|
|
||||||
- name: Create appimage
|
- name: Create appimage
|
||||||
run: |
|
run: |
|
||||||
VERSION=${{ env.CEMU_VERSION }}
|
VERSION=${{ env.CEMU_VERSION }}
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,7 @@ endif()
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
enable_language(OBJC OBJCXX)
|
enable_language(OBJC OBJCXX)
|
||||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "12.0")
|
set(CMAKE_OSX_DEPLOYMENT_TARGET "13.4")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (UNIX AND NOT APPLE)
|
if (UNIX AND NOT APPLE)
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ Cemu is currently only available for 64-bit Windows, Linux & macOS devices.
|
||||||
|
|
||||||
You can download the latest Cemu releases for Windows, Linux and Mac from the [GitHub Releases](https://github.com/cemu-project/Cemu/releases/). For Linux you can also find Cemu on [flathub](https://flathub.org/apps/info.cemu.Cemu).
|
You can download the latest Cemu releases for Windows, Linux and Mac from the [GitHub Releases](https://github.com/cemu-project/Cemu/releases/). For Linux you can also find Cemu on [flathub](https://flathub.org/apps/info.cemu.Cemu).
|
||||||
|
|
||||||
On Windows Cemu is currently only available in a portable format so no installation is required besides extracting it in a safe place.
|
On Windows, Cemu is available both as an installer and in a portable format, where no installation is required besides extracting it in a safe place.
|
||||||
|
|
||||||
The native macOS build is currently purely experimental and should not be considered stable or ready for issue-free gameplay. There are also known issues with degraded performance due to the use of MoltenVK and Rosetta for ARM Macs. We appreciate your patience while we improve Cemu for macOS.
|
The native macOS build is currently purely experimental and should not be considered stable or ready for issue-free gameplay. There are also known issues with degraded performance due to the use of MoltenVK and Rosetta for ARM Macs. We appreciate your patience while we improve Cemu for macOS.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -276,7 +276,7 @@ void IMLRA_DeleteAllRanges(ppcImlGenContext_t* ppcImlGenContext)
|
||||||
for(auto& seg : ppcImlGenContext->segmentList2)
|
for(auto& seg : ppcImlGenContext->segmentList2)
|
||||||
{
|
{
|
||||||
raLivenessRange* cur;
|
raLivenessRange* cur;
|
||||||
while(cur = seg->raInfo.linkedList_allSubranges)
|
while ((cur = seg->raInfo.linkedList_allSubranges))
|
||||||
IMLRA_DeleteRange(ppcImlGenContext, cur);
|
IMLRA_DeleteRange(ppcImlGenContext, cur);
|
||||||
seg->raInfo.linkedList_allSubranges = nullptr;
|
seg->raInfo.linkedList_allSubranges = nullptr;
|
||||||
seg->raInfo.linkedList_perVirtualRegister.clear();
|
seg->raInfo.linkedList_perVirtualRegister.clear();
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ private:
|
||||||
|
|
||||||
D3DKMT_OPENADAPTERFROMHDC OpenAdapterData;
|
D3DKMT_OPENADAPTERFROMHDC OpenAdapterData;
|
||||||
|
|
||||||
*phAdapter = NULL;
|
*phAdapter = 0;
|
||||||
*pOutput = 0;
|
*pOutput = 0;
|
||||||
|
|
||||||
HMONITOR hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
|
HMONITOR hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,33 @@
|
||||||
|
|
||||||
#include "util/helpers/helpers.h"
|
#include "util/helpers/helpers.h"
|
||||||
|
|
||||||
|
#ifdef __arm64__
|
||||||
|
#if defined(__clang__)
|
||||||
|
#include <arm_acle.h>
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
#include <intrin.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void enableFlushDenormalsToZero()
|
||||||
|
{
|
||||||
|
#if defined(ARCH_X86_64)
|
||||||
|
_mm_setcsr(_mm_getcsr() | 0x8000);
|
||||||
|
#elif defined(__arm64__)
|
||||||
|
#if defined(__clang__)
|
||||||
|
__arm_wsr64("fpcr", __arm_rsr64("fpcr") | (1 << 24));
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
__builtin_aarch64_set_fpcr(__builtin_aarch64_get_fpcr() | (1 << 24));
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
_WriteStatusReg(ARM64_FPCR, _ReadStatusReg(ARM64_FPCR) | (1 << 24));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
SlimRWLock srwlock_activeThreadList;
|
SlimRWLock srwlock_activeThreadList;
|
||||||
|
|
||||||
// public list of active threads
|
// public list of active threads
|
||||||
|
|
@ -1321,9 +1348,7 @@ namespace coreinit
|
||||||
#endif
|
#endif
|
||||||
OSHostThread* hostThread = (OSHostThread*)_thread;
|
OSHostThread* hostThread = (OSHostThread*)_thread;
|
||||||
|
|
||||||
#if defined(ARCH_X86_64)
|
enableFlushDenormalsToZero();
|
||||||
_mm_setcsr(_mm_getcsr() | 0x8000); // flush denormals to zero
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PPCInterpreter_t* hCPU = &hostThread->ppcInstance;
|
PPCInterpreter_t* hCPU = &hostThread->ppcInstance;
|
||||||
__OSLoadThread(hostThread->m_thread, hCPU, hostThread->selectedCore);
|
__OSLoadThread(hostThread->m_thread, hCPU, hostThread->selectedCore);
|
||||||
|
|
@ -1369,9 +1394,8 @@ namespace coreinit
|
||||||
{
|
{
|
||||||
SetThreadName(fmt::format("OSSched[core={}]", (uintptr_t)_assignedCoreIndex).c_str());
|
SetThreadName(fmt::format("OSSched[core={}]", (uintptr_t)_assignedCoreIndex).c_str());
|
||||||
t_assignedCoreIndex = (sint32)(uintptr_t)_assignedCoreIndex;
|
t_assignedCoreIndex = (sint32)(uintptr_t)_assignedCoreIndex;
|
||||||
#if defined(ARCH_X86_64)
|
|
||||||
_mm_setcsr(_mm_getcsr() | 0x8000); // flush denormals to zero
|
enableFlushDenormalsToZero();
|
||||||
#endif
|
|
||||||
|
|
||||||
#if BOOST_OS_LINUX
|
#if BOOST_OS_LINUX
|
||||||
if (g_gdbstub)
|
if (g_gdbstub)
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ namespace nn
|
||||||
if (httpCode != 200)
|
if (httpCode != 200)
|
||||||
return OLV_RESULT_STATUS(httpCode + 4000);
|
return OLV_RESULT_STATUS(httpCode + 4000);
|
||||||
|
|
||||||
std::string request_name = doc.select_single_node("//request_name").node().child_value();
|
std::string request_name = doc.select_node("//request_name").node().child_value();
|
||||||
if (request_name.size() == 0)
|
if (request_name.size() == 0)
|
||||||
{
|
{
|
||||||
cemuLog_log(LogType::Force, "Community download response doesn't contain <request_name>");
|
cemuLog_log(LogType::Force, "Community download response doesn't contain <request_name>");
|
||||||
|
|
@ -100,7 +100,7 @@ namespace nn
|
||||||
return OLV_RESULT_INVALID_XML;
|
return OLV_RESULT_INVALID_XML;
|
||||||
}
|
}
|
||||||
|
|
||||||
pugi::xml_node communities = doc.select_single_node("//communities").node();
|
pugi::xml_node communities = doc.select_node("//communities").node();
|
||||||
if (!communities)
|
if (!communities)
|
||||||
{
|
{
|
||||||
cemuLog_log(LogType::Force, "Community download response doesn't contain <communities>");
|
cemuLog_log(LogType::Force, "Community download response doesn't contain <communities>");
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "nn_olv_InitializeTypes.h"
|
#include "nn_olv_InitializeTypes.h"
|
||||||
#include "CafeSystem.h"
|
#include "CafeSystem.h"
|
||||||
#include "Cafe/OS/libs/nn_act/nn_act.h"
|
#include "Cafe/OS/libs/nn_act/nn_act.h"
|
||||||
|
|
|
||||||
|
|
@ -38,12 +38,12 @@ namespace nn
|
||||||
if (!pParam->communityId)
|
if (!pParam->communityId)
|
||||||
return OLV_RESULT_INVALID_PARAMETER;
|
return OLV_RESULT_INVALID_PARAMETER;
|
||||||
|
|
||||||
snprintf(requestUrl, sizeof(requestUrl), "%s/v1/communities/%lu.delete", g_DiscoveryResults.apiEndpoint, pParam->communityId.value());
|
snprintf(requestUrl, sizeof(requestUrl), "%s/v1/communities/%u.delete", g_DiscoveryResults.apiEndpoint, pParam->communityId.value());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (pParam->communityId)
|
if (pParam->communityId)
|
||||||
snprintf(requestUrl, sizeof(requestUrl), "%s/v1/communities/%lu", g_DiscoveryResults.apiEndpoint, pParam->communityId.value());
|
snprintf(requestUrl, sizeof(requestUrl), "%s/v1/communities/%u", g_DiscoveryResults.apiEndpoint, pParam->communityId.value());
|
||||||
else
|
else
|
||||||
snprintf(requestUrl, sizeof(requestUrl), "%s/v1/communities", g_DiscoveryResults.apiEndpoint);
|
snprintf(requestUrl, sizeof(requestUrl), "%s/v1/communities", g_DiscoveryResults.apiEndpoint);
|
||||||
}
|
}
|
||||||
|
|
@ -223,12 +223,12 @@ namespace nn
|
||||||
if (pOutData)
|
if (pOutData)
|
||||||
{
|
{
|
||||||
|
|
||||||
std::string_view app_data = doc.select_single_node("//app_data").node().child_value();
|
std::string_view app_data = doc.select_node("//app_data").node().child_value();
|
||||||
std::string_view community_id = doc.select_single_node("//community_id").node().child_value();
|
std::string_view community_id = doc.select_node("//community_id").node().child_value();
|
||||||
std::string_view name = doc.select_single_node("//name").node().child_value();
|
std::string_view name = doc.select_node("//name").node().child_value();
|
||||||
std::string_view description = doc.select_single_node("//description").node().child_value();
|
std::string_view description = doc.select_node("//description").node().child_value();
|
||||||
std::string_view pid = doc.select_single_node("//pid").node().child_value();
|
std::string_view pid = doc.select_node("//pid").node().child_value();
|
||||||
std::string_view icon = doc.select_single_node("//icon").node().child_value();
|
std::string_view icon = doc.select_node("//icon").node().child_value();
|
||||||
|
|
||||||
if (app_data.size() != 0)
|
if (app_data.size() != 0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,9 @@ namespace nn
|
||||||
|
|
||||||
char requestUrl[512];
|
char requestUrl[512];
|
||||||
if (pParam->flags & UploadFavoriteToCommunityDataParam::FLAG_DELETION)
|
if (pParam->flags & UploadFavoriteToCommunityDataParam::FLAG_DELETION)
|
||||||
snprintf(requestUrl, sizeof(requestUrl), "%s/v1/communities/%lu.unfavorite", g_DiscoveryResults.apiEndpoint, pParam->communityId.value());
|
snprintf(requestUrl, sizeof(requestUrl), "%s/v1/communities/%u.unfavorite", g_DiscoveryResults.apiEndpoint, pParam->communityId.value());
|
||||||
else
|
else
|
||||||
snprintf(requestUrl, sizeof(requestUrl), "%s/v1/communities/%lu.favorite", g_DiscoveryResults.apiEndpoint, pParam->communityId.value());
|
snprintf(requestUrl, sizeof(requestUrl), "%s/v1/communities/%u.favorite", g_DiscoveryResults.apiEndpoint, pParam->communityId.value());
|
||||||
|
|
||||||
CurlRequestHelper req;
|
CurlRequestHelper req;
|
||||||
req.initate(ActiveSettings::GetNetworkService(), requestUrl, CurlRequestHelper::SERVER_SSL_CONTEXT::OLIVE);
|
req.initate(ActiveSettings::GetNetworkService(), requestUrl, CurlRequestHelper::SERVER_SSL_CONTEXT::OLIVE);
|
||||||
|
|
@ -88,12 +88,12 @@ namespace nn
|
||||||
|
|
||||||
if (pOutData)
|
if (pOutData)
|
||||||
{
|
{
|
||||||
std::string_view app_data = doc.select_single_node("//app_data").node().child_value();
|
std::string_view app_data = doc.select_node("//app_data").node().child_value();
|
||||||
std::string_view community_id = doc.select_single_node("//community_id").node().child_value();
|
std::string_view community_id = doc.select_node("//community_id").node().child_value();
|
||||||
std::string_view name = doc.select_single_node("//name").node().child_value();
|
std::string_view name = doc.select_node("//name").node().child_value();
|
||||||
std::string_view description = doc.select_single_node("//description").node().child_value();
|
std::string_view description = doc.select_node("//description").node().child_value();
|
||||||
std::string_view pid = doc.select_single_node("//pid").node().child_value();
|
std::string_view pid = doc.select_node("//pid").node().child_value();
|
||||||
std::string_view icon = doc.select_single_node("//icon").node().child_value();
|
std::string_view icon = doc.select_node("//icon").node().child_value();
|
||||||
|
|
||||||
if (app_data.size() != 0)
|
if (app_data.size() != 0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -413,13 +413,12 @@ namespace snd_core
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_padVolume = GetConfig().pad_volume;
|
||||||
if (!g_padAudio)
|
if (!g_padAudio)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
g_padAudio = IAudioAPI::CreateDeviceFromConfig(IAudioAPI::AudioType::Gamepad, 48000, snd_core::AX_SAMPLES_PER_3MS_48KHZ * AX_FRAMES_PER_GROUP, 16);
|
g_padAudio = IAudioAPI::CreateDeviceFromConfig(IAudioAPI::AudioType::Gamepad, 48000, snd_core::AX_SAMPLES_PER_3MS_48KHZ * AX_FRAMES_PER_GROUP, 16);
|
||||||
if(g_padAudio)
|
|
||||||
g_padVolume = g_padAudio->GetVolume();
|
|
||||||
}
|
}
|
||||||
catch (std::runtime_error& ex)
|
catch (std::runtime_error& ex)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1216,11 +1216,10 @@ void GeneralSettings2::OnVolumeChanged(wxCommandEvent& event)
|
||||||
if(event.GetEventObject() == m_pad_volume)
|
if(event.GetEventObject() == m_pad_volume)
|
||||||
{
|
{
|
||||||
if (g_padAudio)
|
if (g_padAudio)
|
||||||
{
|
|
||||||
g_padAudio->SetVolume(event.GetInt());
|
g_padAudio->SetVolume(event.GetInt());
|
||||||
|
|
||||||
g_padVolume = event.GetInt();
|
g_padVolume = event.GetInt();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if (event.GetEventObject() == m_tv_volume)
|
else if (event.GetEventObject() == m_tv_volume)
|
||||||
{
|
{
|
||||||
if (g_tvAudio)
|
if (g_tvAudio)
|
||||||
|
|
@ -1241,10 +1240,7 @@ void GeneralSettings2::OnInputVolumeChanged(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
std::shared_lock lock(g_audioMutex);
|
std::shared_lock lock(g_audioMutex);
|
||||||
if (g_padAudio)
|
if (g_padAudio)
|
||||||
{
|
|
||||||
g_padAudio->SetInputVolume(event.GetInt());
|
g_padAudio->SetInputVolume(event.GetInt());
|
||||||
g_padVolume = event.GetInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
event.Skip();
|
event.Skip();
|
||||||
}
|
}
|
||||||
|
|
@ -1947,11 +1943,12 @@ void GeneralSettings2::UpdateAudioDevice()
|
||||||
else
|
else
|
||||||
channels = CemuConfig::AudioChannelsToNChannels(config.pad_channels);
|
channels = CemuConfig::AudioChannelsToNChannels(config.pad_channels);
|
||||||
|
|
||||||
|
g_padVolume = m_pad_volume->GetValue();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
g_padAudio = IAudioAPI::CreateDevice((IAudioAPI::AudioAPI)config.audio_api, description->GetDescription(), 48000, channels, snd_core::AX_SAMPLES_PER_3MS_48KHZ * AX_FRAMES_PER_GROUP, 16);
|
g_padAudio = IAudioAPI::CreateDevice((IAudioAPI::AudioAPI)config.audio_api, description->GetDescription(), 48000, channels, snd_core::AX_SAMPLES_PER_3MS_48KHZ * AX_FRAMES_PER_GROUP, 16);
|
||||||
g_padAudio->SetVolume(m_pad_volume->GetValue());
|
g_padAudio->SetVolume(m_pad_volume->GetValue());
|
||||||
g_padVolume = m_pad_volume->GetValue();
|
|
||||||
}
|
}
|
||||||
catch (std::runtime_error& ex)
|
catch (std::runtime_error& ex)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -514,6 +514,9 @@ std::weak_ordering wxGameList::SortComparator(uint64 titleId1, uint64 titleId2,
|
||||||
return CafeTitleList::GetGameInfo(id).GetRegion();
|
return CafeTitleList::GetGameInfo(id).GetRegion();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!sortData->asc)
|
||||||
|
std::swap(titleId1, titleId2);
|
||||||
|
|
||||||
switch(sortData->column)
|
switch(sortData->column)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
|
|
@ -542,7 +545,7 @@ std::weak_ordering wxGameList::SortComparator(uint64 titleId1, uint64 titleId2,
|
||||||
int wxGameList::SortFunction(wxIntPtr item1, wxIntPtr item2, wxIntPtr sortData)
|
int wxGameList::SortFunction(wxIntPtr item1, wxIntPtr item2, wxIntPtr sortData)
|
||||||
{
|
{
|
||||||
const auto sort_data = (SortData*)sortData;
|
const auto sort_data = (SortData*)sortData;
|
||||||
return sort_data->dir * order_to_int(sort_data->thisptr->SortComparator((uint64)item1, (uint64)item2, sort_data));
|
return order_to_int(sort_data->thisptr->SortComparator((uint64)item1, (uint64)item2, sort_data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxGameList::SortEntries(int column)
|
void wxGameList::SortEntries(int column)
|
||||||
|
|
@ -566,7 +569,7 @@ void wxGameList::SortEntries(int column)
|
||||||
case ColumnRegion:
|
case ColumnRegion:
|
||||||
case ColumnTitleID:
|
case ColumnTitleID:
|
||||||
{
|
{
|
||||||
SortData data{this, ItemColumns{column}, ascending ? 1 : -1};
|
SortData data{this, ItemColumns{column}, ascending};
|
||||||
SortItems(SortFunction, (wxIntPtr)&data);
|
SortItems(SortFunction, (wxIntPtr)&data);
|
||||||
ShowSortIndicator(column, ascending);
|
ShowSortIndicator(column, ascending);
|
||||||
break;
|
break;
|
||||||
|
|
@ -1677,7 +1680,8 @@ void wxGameList::CreateShortcut(GameInfo2& gameInfo)
|
||||||
hres = shellLinkFile->Save(outputPath.wc_str(), TRUE);
|
hres = shellLinkFile->Save(outputPath.wc_str(), TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!SUCCEEDED(hres)) {
|
if (FAILED(hres))
|
||||||
|
{
|
||||||
auto errorMsg = formatWxString(_("Failed to save shortcut to {}"), outputPath);
|
auto errorMsg = formatWxString(_("Failed to save shortcut to {}"), outputPath);
|
||||||
wxMessageBox(errorMsg, _("Error"), wxOK | wxCENTRE | wxICON_ERROR);
|
wxMessageBox(errorMsg, _("Error"), wxOK | wxCENTRE | wxICON_ERROR);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ private:
|
||||||
{
|
{
|
||||||
wxGameList* thisptr;
|
wxGameList* thisptr;
|
||||||
ItemColumns column;
|
ItemColumns column;
|
||||||
int dir;
|
bool asc;
|
||||||
};
|
};
|
||||||
|
|
||||||
int FindInsertPosition(TitleId titleId);
|
int FindInsertPosition(TitleId titleId);
|
||||||
|
|
|
||||||
|
|
@ -344,6 +344,9 @@ void WiimoteControllerProvider::reader_thread()
|
||||||
new_state.m_extension = {};
|
new_state.m_extension = {};
|
||||||
request_status(index);
|
request_status(index);
|
||||||
break;
|
break;
|
||||||
|
case kExtensionMotionPlusInactive:
|
||||||
|
cemuLog_logDebug(LogType::Force,"Extension Type Received: Inactive MotionPlus");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
cemuLog_logDebug(LogType::Force,"Unknown extension: {:#x}", be_type.value());
|
cemuLog_logDebug(LogType::Force,"Unknown extension: {:#x}", be_type.value());
|
||||||
new_state.m_extension = {};
|
new_state.m_extension = {};
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ enum ExtensionType : uint64
|
||||||
kExtensionDrums = 0x0100A4200103,
|
kExtensionDrums = 0x0100A4200103,
|
||||||
kExtensionBalanceBoard = 0x2A2C,
|
kExtensionBalanceBoard = 0x2A2C,
|
||||||
|
|
||||||
|
kExtensionMotionPlusInactive = 0xa4200005,
|
||||||
kExtensionMotionPlus = 0xa6200005,
|
kExtensionMotionPlus = 0xa6200005,
|
||||||
|
|
||||||
kExtensionPartialyInserted = 0xffffffffffff,
|
kExtensionPartialyInserted = 0xffffffffffff,
|
||||||
|
|
|
||||||
172
src/resource/installer.nsi
Normal file
172
src/resource/installer.nsi
Normal file
|
|
@ -0,0 +1,172 @@
|
||||||
|
; Copyright Dolphin Emulator Project / Azahar Emulator Project / Team Cemu
|
||||||
|
; Licensed under MPL 2.0 with permission from authors
|
||||||
|
|
||||||
|
; Usage:
|
||||||
|
; get the latest nsis: https://nsis.sourceforge.io/Download
|
||||||
|
; probably also want vscode extension: https://marketplace.visualstudio.com/items?itemName=idleberg.nsis
|
||||||
|
|
||||||
|
; Require /DPRODUCT_VERSION for makensis.
|
||||||
|
!ifndef PRODUCT_VERSION
|
||||||
|
!error "PRODUCT_VERSION must be defined"
|
||||||
|
!endif
|
||||||
|
|
||||||
|
ManifestDPIAware true
|
||||||
|
|
||||||
|
!define PRODUCT_NAME "Cemu"
|
||||||
|
!define PRODUCT_PUBLISHER "Team Cemu"
|
||||||
|
!define PRODUCT_WEB_SITE "https://cemu.info/"
|
||||||
|
!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\${PRODUCT_NAME}.exe"
|
||||||
|
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
|
||||||
|
|
||||||
|
!define BINARY_SOURCE_DIR "..\..\bin"
|
||||||
|
|
||||||
|
Name "${PRODUCT_NAME}"
|
||||||
|
OutFile "cemu-${PRODUCT_VERSION}-windows-x64-installer.exe"
|
||||||
|
SetCompressor /SOLID lzma
|
||||||
|
InstallDir "$LOCALAPPDATA\Cemu"
|
||||||
|
ShowInstDetails show
|
||||||
|
ShowUnInstDetails show
|
||||||
|
|
||||||
|
!include "MUI2.nsh"
|
||||||
|
; Custom page plugin
|
||||||
|
!include "nsDialogs.nsh"
|
||||||
|
|
||||||
|
; MUI Settings
|
||||||
|
!define MUI_ICON "logo_icon.ico"
|
||||||
|
!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"
|
||||||
|
|
||||||
|
; License page
|
||||||
|
!insertmacro MUI_PAGE_LICENSE "..\..\LICENSE.txt"
|
||||||
|
; Desktop Shortcut page
|
||||||
|
Page custom desktopShortcutPageCreate desktopShortcutPageLeave
|
||||||
|
; Directory page
|
||||||
|
!insertmacro MUI_PAGE_DIRECTORY
|
||||||
|
; Instfiles page
|
||||||
|
!insertmacro MUI_PAGE_INSTFILES
|
||||||
|
; Finish page
|
||||||
|
!define MUI_FINISHPAGE_RUN "$INSTDIR\Cemu.exe"
|
||||||
|
!insertmacro MUI_PAGE_FINISH
|
||||||
|
|
||||||
|
; Uninstaller pages
|
||||||
|
!insertmacro MUI_UNPAGE_INSTFILES
|
||||||
|
|
||||||
|
; Variables
|
||||||
|
Var DesktopShortcutPageDialog
|
||||||
|
Var DesktopShortcutCheckbox
|
||||||
|
Var DesktopShortcut
|
||||||
|
|
||||||
|
; Language files
|
||||||
|
!insertmacro MUI_LANGUAGE "English"
|
||||||
|
!insertmacro MUI_LANGUAGE "SimpChinese"
|
||||||
|
!insertmacro MUI_LANGUAGE "TradChinese"
|
||||||
|
!insertmacro MUI_LANGUAGE "Danish"
|
||||||
|
!insertmacro MUI_LANGUAGE "Dutch"
|
||||||
|
!insertmacro MUI_LANGUAGE "French"
|
||||||
|
!insertmacro MUI_LANGUAGE "German"
|
||||||
|
!insertmacro MUI_LANGUAGE "Hungarian"
|
||||||
|
!insertmacro MUI_LANGUAGE "Italian"
|
||||||
|
!insertmacro MUI_LANGUAGE "Japanese"
|
||||||
|
!insertmacro MUI_LANGUAGE "Korean"
|
||||||
|
!insertmacro MUI_LANGUAGE "Lithuanian"
|
||||||
|
!insertmacro MUI_LANGUAGE "Norwegian"
|
||||||
|
!insertmacro MUI_LANGUAGE "Polish"
|
||||||
|
!insertmacro MUI_LANGUAGE "PortugueseBR"
|
||||||
|
!insertmacro MUI_LANGUAGE "Romanian"
|
||||||
|
!insertmacro MUI_LANGUAGE "Russian"
|
||||||
|
!insertmacro MUI_LANGUAGE "Spanish"
|
||||||
|
!insertmacro MUI_LANGUAGE "Swedish"
|
||||||
|
!insertmacro MUI_LANGUAGE "Turkish"
|
||||||
|
!insertmacro MUI_LANGUAGE "Vietnamese"
|
||||||
|
|
||||||
|
; MUI end ------
|
||||||
|
|
||||||
|
Function .onInit
|
||||||
|
StrCpy $DesktopShortcut 1
|
||||||
|
|
||||||
|
!insertmacro MUI_LANGDLL_DISPLAY
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Function desktopShortcutPageCreate
|
||||||
|
!insertmacro MUI_HEADER_TEXT "Create Desktop Shortcut" "Would you like to create a desktop shortcut?"
|
||||||
|
nsDialogs::Create 1018
|
||||||
|
Pop $DesktopShortcutPageDialog
|
||||||
|
${If} $DesktopShortcutPageDialog == error
|
||||||
|
Abort
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
${NSD_CreateCheckbox} 0u 0u 100% 12u "Create a desktop shortcut"
|
||||||
|
Pop $DesktopShortcutCheckbox
|
||||||
|
${NSD_SetState} $DesktopShortcutCheckbox $DesktopShortcut
|
||||||
|
|
||||||
|
nsDialogs::Show
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Function desktopShortcutPageLeave
|
||||||
|
${NSD_GetState} $DesktopShortcutCheckbox $DesktopShortcut
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Section "Base"
|
||||||
|
ExecWait '"$INSTDIR\uninst.exe" /S _?=$INSTDIR'
|
||||||
|
|
||||||
|
SectionIn RO
|
||||||
|
|
||||||
|
SetOutPath "$INSTDIR"
|
||||||
|
|
||||||
|
; The binplaced build output will be included verbatim.
|
||||||
|
File /r "${BINARY_SOURCE_DIR}\*"
|
||||||
|
|
||||||
|
; Create start menu and desktop shortcuts
|
||||||
|
CreateShortCut "$SMPROGRAMS\$(^Name).lnk" "$INSTDIR\Cemu.exe"
|
||||||
|
${If} $DesktopShortcut == 1
|
||||||
|
CreateShortCut "$DESKTOP\$(^Name).lnk" "$INSTDIR\Cemu.exe"
|
||||||
|
${EndIf}
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
!include "FileFunc.nsh"
|
||||||
|
|
||||||
|
Section -Post
|
||||||
|
WriteUninstaller "$INSTDIR\uninst.exe"
|
||||||
|
|
||||||
|
WriteRegStr HKCU "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\Cemu.exe"
|
||||||
|
|
||||||
|
; Write metadata for add/remove programs applet
|
||||||
|
WriteRegStr HKCU "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
|
||||||
|
WriteRegStr HKCU "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
|
||||||
|
WriteRegStr HKCU "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\Cemu.exe"
|
||||||
|
WriteRegStr HKCU "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
|
||||||
|
WriteRegStr HKCU "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
|
||||||
|
WriteRegStr HKCU "${PRODUCT_UNINST_KEY}" "InstallLocation" "$INSTDIR"
|
||||||
|
${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
|
||||||
|
IntFmt $0 "0x%08X" $0
|
||||||
|
WriteRegDWORD HKCU "${PRODUCT_UNINST_KEY}" "EstimatedSize" "$0"
|
||||||
|
|
||||||
|
WriteRegStr HKCU "Software\Classes\.wud" "" "$(^Name)"
|
||||||
|
WriteRegStr HKCU "Software\Classes\.wux" "" "$(^Name)"
|
||||||
|
WriteRegStr HKCU "Software\Classes\.wua" "" "$(^Name)"
|
||||||
|
WriteRegStr HKCU "Software\Classes\$(^Name)\DefaultIcon" "" "$INSTDIR\Cemu.exe,0"
|
||||||
|
WriteRegStr HKCU "Software\Classes\$(^Name)\Shell\open\command" "" '"$INSTDIR\Cemu.exe" %1'
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section Uninstall
|
||||||
|
Delete "$DESKTOP\$(^Name).lnk"
|
||||||
|
Delete "$SMPROGRAMS\$(^Name).lnk"
|
||||||
|
|
||||||
|
; Be a bit careful to not delete files a user may have put into the install directory
|
||||||
|
Delete "$INSTDIR\Cemu.exe"
|
||||||
|
Delete "$INSTDIR\uninst.exe"
|
||||||
|
RMDir /r "$INSTDIR\gameProfiles"
|
||||||
|
RMDir /r "$INSTDIR\resources"
|
||||||
|
RMDir "$INSTDIR"
|
||||||
|
|
||||||
|
DeleteRegKey HKCU "Software\Classes\.wud"
|
||||||
|
DeleteRegKey HKCU "Software\Classes\.wux"
|
||||||
|
DeleteRegKey HKCU "Software\Classes\.wua"
|
||||||
|
DeleteRegKey HKCU "Software\Classes\$(^Name)"
|
||||||
|
|
||||||
|
DeleteRegKey HKCU "Software\Classes\discord-460807638964371468"
|
||||||
|
|
||||||
|
DeleteRegKey HKCU "${PRODUCT_UNINST_KEY}"
|
||||||
|
DeleteRegKey HKCU "${PRODUCT_DIR_REGKEY}"
|
||||||
|
|
||||||
|
SetAutoClose true
|
||||||
|
SectionEnd
|
||||||
|
|
@ -283,7 +283,7 @@ private:
|
||||||
{
|
{
|
||||||
if (itr.chunkIndex != dbgRange.chunkIndex)
|
if (itr.chunkIndex != dbgRange.chunkIndex)
|
||||||
continue;
|
continue;
|
||||||
if (itr.offset < (dbgRange.offset + dbgRange.size) && (itr.offset + itr.size) >(dbgRange.offset))
|
if (itr.offset < (dbgRange.offset + dbgRange.size) && (itr.offset + itr.size) > dbgRange.offset)
|
||||||
cemu_assert_error();
|
cemu_assert_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue