Added mechanism for stable/experimental/dev version

-DEXPERIMENTAL_VERSION can be used to specify (non-zero) experimental version. It will show as LEAD.MAJOR-MINOR. It will also set the (experimental) suffix in Cemu's name. If not specified, the suffix will be empty and the version shows as LEAD.MAJOR
If PUBLIC_RELEASE is not set the suffix will be (dev)
Also updated the auto-updater to use a new API that supports our github releases
This commit is contained in:
Exzap 2022-08-31 06:30:00 +02:00
parent 527ee3aea5
commit ae6e6f9f79
13 changed files with 150 additions and 93 deletions

View file

@ -2,12 +2,17 @@ cmake_minimum_required(VERSION 3.21.1)
option(PUBLIC_RELEASE "Compile with debug asserts disabled and no console" OFF) option(PUBLIC_RELEASE "Compile with debug asserts disabled and no console" OFF)
option(ENABLE_VCPKG "Enable the vcpkg package manager" ON) option(ENABLE_VCPKG "Enable the vcpkg package manager" ON)
set(EXPERIMENTAL_VERSION "" CACHE STRING "") # used by CI script to set experimental version
if (PUBLIC_RELEASE) if (PUBLIC_RELEASE)
add_definitions(-DPUBLIC_RELEASE) add_definitions(-DPUBLIC_RELEASE)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) # enable LTO set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) # enable LTO
endif() endif()
if (EXPERIMENTAL_VERSION)
add_definitions(-DEMULATOR_VERSION_MINOR=${EXPERIMENTAL_VERSION})
endif()
if (ENABLE_VCPKG) if (ENABLE_VCPKG)
set(VCPKG_OVERLAY_PORTS "${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports") set(VCPKG_OVERLAY_PORTS "${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports")
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/vcpkg/scripts/buildsystems/vcpkg.cmake" set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/vcpkg/scripts/buildsystems/vcpkg.cmake"

View file

@ -37,13 +37,10 @@ void DiscordPresence::UpdatePresence(State state, const std::string& text) const
break; break;
} }
char image_text[128];
sprintf(image_text, EMULATOR_NAME" %d.%d%s", EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_SUFFIX);
discord_presence.details = details_string.c_str(); discord_presence.details = details_string.c_str();
discord_presence.state = state_string.c_str(); discord_presence.state = state_string.c_str();
discord_presence.startTimestamp = time(nullptr); discord_presence.startTimestamp = time(nullptr);
discord_presence.largeImageText = image_text; discord_presence.largeImageText = BUILD_VERSION_WITH_NAME_STRING;
discord_presence.largeImageKey = "logo_icon_big_png"; discord_presence.largeImageKey = "logo_icon_big_png";
Discord_UpdatePresence(&discord_presence); Discord_UpdatePresence(&discord_presence);
} }

View file

@ -195,7 +195,7 @@ void createCrashlog(EXCEPTION_POINTERS* e, PCONTEXT context)
char dumpLine[1024 * 4]; char dumpLine[1024 * 4];
// info about Cemu version // info about Cemu version
sprintf(dumpLine, "\nCrashlog for Cemu %d.%d%s\n", EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_SUFFIX); sprintf(dumpLine, "\nCrashlog for %s\n", BUILD_VERSION_WITH_NAME_STRING);
cemuLog_writePlainToLog(dumpLine); cemuLog_writePlainToLog(dumpLine);
SYSTEMTIME sysTime; SYSTEMTIME sysTime;

View file

@ -1,8 +1,33 @@
#ifndef EMULATOR_NAME
#define EMULATOR_NAME "Cemu" #define EMULATOR_NAME "Cemu"
#define EMULATOR_VERSION_LEAD 2 #define EMULATOR_VERSION_LEAD 2
#define EMULATOR_VERSION_MAJOR 0 #define EMULATOR_VERSION_MAJOR 0
#define EMULATOR_VERSION_MINOR 0 // kept internally for backwards compatibility purposes, but isn't displayed anymore
// the minor version is used for experimental builds to indicate the build index. Set by command line option from CI build script
// if zero, the version text will be constructed as LEAD.MAJOR, otherwise as LEAD.MAJOR-MINOR
#if !defined(PUBLIC_RELEASE)
#define EMULATOR_VERSION_SUFFIX " (dev)"
#elif defined(EMULATOR_VERSION_MINOR) && EMULATOR_VERSION_MINOR == 0
#define EMULATOR_VERSION_SUFFIX "" // stable
#else
#define EMULATOR_VERSION_SUFFIX " (experimental)" #define EMULATOR_VERSION_SUFFIX " (experimental)"
#endif
#define EMULATOR_SERVER_VERSION 4000 // used for auto-updater, increment this with every release #ifndef EMULATOR_VERSION_MINOR
#define EMULATOR_VERSION_MINOR 0
#endif
#define _XSTRINGFY(s) _STRINGFY(s)
#define _STRINGFY(s) #s
#if EMULATOR_VERSION_MINOR != 0
#define BUILD_VERSION_WITH_NAME_STRING (EMULATOR_NAME " " _XSTRINGFY(EMULATOR_VERSION_LEAD) "." _XSTRINGFY(EMULATOR_VERSION_MAJOR) "-" _XSTRINGFY(EMULATOR_VERSION_MINOR) EMULATOR_VERSION_SUFFIX)
#define BUILD_VERSION_STRING (_XSTRINGFY(EMULATOR_VERSION_LEAD) "." _XSTRINGFY(EMULATOR_VERSION_MAJOR) "-" _XSTRINGFY(EMULATOR_VERSION_MINOR) EMULATOR_VERSION_SUFFIX)
#else
#define BUILD_VERSION_STRING (_XSTRINGFY(EMULATOR_VERSION_LEAD) "." _XSTRINGFY(EMULATOR_VERSION_MAJOR) EMULATOR_VERSION_SUFFIX)
#define BUILD_VERSION_WITH_NAME_STRING (EMULATOR_NAME " " _XSTRINGFY(EMULATOR_VERSION_LEAD) "." _XSTRINGFY(EMULATOR_VERSION_MAJOR) EMULATOR_VERSION_SUFFIX)
#endif
#endif

View file

@ -112,7 +112,12 @@ bool LaunchSettings::HandleCommandline(const std::vector<std::wstring>& args)
if (vm.count("version")) if (vm.count("version"))
{ {
requireConsole(); requireConsole();
std::string versionStr = fmt::format("{}.{}{}", EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_SUFFIX); std::string versionStr;
#if EMULATOR_VERSION_MINOR == 0
versionStr = fmt::format("{}.{}{}", EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_SUFFIX);
#else
versionStr = fmt::format("{}.{}-{}{}", EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR, EMULATOR_VERSION_SUFFIX);
#endif
std::cout << versionStr << std::endl; std::cout << versionStr << std::endl;
return false; // exit in main return false; // exit in main
} }

View file

@ -40,13 +40,13 @@ CemuUpdateWindow::CemuUpdateWindow(wxWindow* parent)
{ {
auto* right_side = new wxBoxSizer(wxHORIZONTAL); auto* right_side = new wxBoxSizer(wxHORIZONTAL);
m_update_button = new wxButton(this, wxID_ANY, _("Update")); m_updateButton = new wxButton(this, wxID_ANY, _("Update"));
m_update_button->Bind(wxEVT_BUTTON, &CemuUpdateWindow::OnUpdateButton, this); m_updateButton->Bind(wxEVT_BUTTON, &CemuUpdateWindow::OnUpdateButton, this);
right_side->Add(m_update_button, 0, wxALL, 5); right_side->Add(m_updateButton, 0, wxALL, 5);
m_cancel_button = new wxButton(this, wxID_ANY, _("Cancel")); m_cancelButton = new wxButton(this, wxID_ANY, _("Cancel"));
m_cancel_button->Bind(wxEVT_BUTTON, &CemuUpdateWindow::OnCancelButton, this); m_cancelButton->Bind(wxEVT_BUTTON, &CemuUpdateWindow::OnCancelButton, this);
right_side->Add(m_cancel_button, 0, wxALL, 5); right_side->Add(m_cancelButton, 0, wxALL, 5);
rows->Add(right_side, 1, wxALIGN_RIGHT, 5); rows->Add(right_side, 1, wxALIGN_RIGHT, 5);
} }
@ -64,7 +64,7 @@ CemuUpdateWindow::CemuUpdateWindow(wxWindow* parent)
Bind(wxEVT_PROGRESS, &CemuUpdateWindow::OnGaugeUpdate, this); Bind(wxEVT_PROGRESS, &CemuUpdateWindow::OnGaugeUpdate, this);
m_thread = std::thread(&CemuUpdateWindow::WorkerThread, this); m_thread = std::thread(&CemuUpdateWindow::WorkerThread, this);
m_update_button->Hide(); m_updateButton->Hide();
m_changelog->Hide(); m_changelog->Hide();
} }
@ -89,14 +89,32 @@ std::string _curlUrlEscape(CURL* curl, const std::string& input)
return r; return r;
} }
bool CemuUpdateWindow::GetServerVersion(uint64& version, std::string& filename, std::string& changelog_filename) std::string _curlUrlUnescape(CURL* curl, std::string_view input)
{
int decodedLen = 0;
const char* decoded = curl_easy_unescape(curl, input.data(), input.size(), &decodedLen);
return std::string(decoded, decodedLen);
}
// returns true if update is available and sets output parameters
bool CemuUpdateWindow::QueryUpdateInfo(std::string& downloadUrlOut, std::string& changelogUrlOut)
{ {
std::string buffer; std::string buffer;
std::string urlStr("https://cemu.info/api/cemu_version3.php?version2="); std::string urlStr("https://cemu.info/api2/version.php?v=");
auto* curl = curl_easy_init(); auto* curl = curl_easy_init();
urlStr.append(_curlUrlEscape(curl, fmt::format("{}.{}.{}{}", EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR, EMULATOR_VERSION_SUFFIX))); urlStr.append(_curlUrlEscape(curl, BUILD_VERSION_STRING));
#if BOOST_OS_LINUX
urlStr.append("&platform=linux");
#elif BOOST_OS_WINDOWS
urlStr.append("&platform=windows");
#elif BOOST_OS_MACOS
urlStr.append("&platform=macos_x86");
#elif
#error Name for current platform is missing
#endif
curl_easy_setopt(curl, CURLOPT_URL, urlStr.c_str()); curl_easy_setopt(curl, CURLOPT_URL, urlStr.c_str());
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteStringCallback); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteStringCallback);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
@ -118,22 +136,17 @@ bool CemuUpdateWindow::GetServerVersion(uint64& version, std::string& filename,
std::vector<std::string> tokens; std::vector<std::string> tokens;
const boost::char_separator<char> sep{ "|" }; const boost::char_separator<char> sep{ "|" };
for (const auto& token : boost::tokenizer(buffer, sep)) for (const auto& token : boost::tokenizer(buffer, sep))
{
tokens.emplace_back(token); tokens.emplace_back(token);
}
if (tokens.size() >= 2) if (tokens.size() >= 2)
{ {
const auto latest_version = ConvertString<uint64>(tokens[0]); // first token: Download URL
result = latest_version > 0 && !tokens[1].empty(); // second token: Changelog URL
if (result) // we allow more tokens in case we ever want to add extra information for future releases
{ downloadUrlOut = _curlUrlUnescape(curl, tokens[0]);
version = latest_version; changelogUrlOut = _curlUrlUnescape(curl, tokens[1]);
filename = tokens[1]; if (!downloadUrlOut.empty() && !changelogUrlOut.empty())
result = true;
if(tokens.size() >= 3)
changelog_filename = tokens[2];
}
} }
} }
else else
@ -146,27 +159,17 @@ bool CemuUpdateWindow::GetServerVersion(uint64& version, std::string& filename,
return result; return result;
} }
std::future<bool> CemuUpdateWindow::IsUpdateAvailable() std::future<bool> CemuUpdateWindow::IsUpdateAvailableAsync()
{ {
return std::async(std::launch::async, CheckVersion); return std::async(std::launch::async, CheckVersion);
} }
bool CemuUpdateWindow::CheckVersion() bool CemuUpdateWindow::CheckVersion()
{ {
uint64 latest_version; std::string downloadUrl, changelogUrl;
std::string filename, changelog; return QueryUpdateInfo(downloadUrl, changelogUrl);
if (!GetServerVersion(latest_version, filename, changelog))
return false;
return IsUpdateAvailable(latest_version);
} }
bool CemuUpdateWindow::IsUpdateAvailable(uint64 latest_version)
{
uint64 version = EMULATOR_SERVER_VERSION;
return latest_version > version;
}
int CemuUpdateWindow::ProgressCallback(void* clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, int CemuUpdateWindow::ProgressCallback(void* clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal,
curl_off_t ulnow) curl_off_t ulnow)
@ -188,7 +191,11 @@ bool CemuUpdateWindow::DownloadCemuZip(const std::string& url, const fs::path& f
auto* curl = curl_easy_init(); auto* curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_NOBODY, 1); curl_easy_setopt(curl, CURLOPT_NOBODY, 1);
if (curl_easy_perform(curl) == CURLE_OK) curl_easy_setopt(curl, CURLOPT_USERAGENT, BUILD_VERSION_WITH_NAME_STRING);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
auto r = curl_easy_perform(curl);
if (r == CURLE_OK)
{ {
long http_code = 0; long http_code = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
@ -201,7 +208,7 @@ bool CemuUpdateWindow::DownloadCemuZip(const std::string& url, const fs::path& f
curl_off_t update_size; curl_off_t update_size;
if (curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &update_size) == CURLE_OK) if (curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &update_size) == CURLE_OK)
m_gauge_max_value = (int)update_size; m_gaugeMaxValue = (int)update_size;
auto _curlWriteData = +[](void* ptr, size_t size, size_t nmemb, void* ctx) -> size_t auto _curlWriteData = +[](void* ptr, size_t size, size_t nmemb, void* ctx) -> size_t
@ -238,7 +245,10 @@ bool CemuUpdateWindow::DownloadCemuZip(const std::string& url, const fs::path& f
delete fsUpdateFile; delete fsUpdateFile;
} }
else else
{
cemuLog_log(LogType::Force, "Cemu zip download failed with error {}", r);
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
}
if (!result && fs::exists(filename)) if (!result && fs::exists(filename))
{ {
@ -254,8 +264,9 @@ bool CemuUpdateWindow::DownloadCemuZip(const std::string& url, const fs::path& f
return result; return result;
} }
bool CemuUpdateWindow::ExtractUpdate(const fs::path& zipname, const fs::path& targetpath) bool CemuUpdateWindow::ExtractUpdate(const fs::path& zipname, const fs::path& targetpath, std::string& cemuFolderName)
{ {
cemuFolderName.clear();
// open downloaded zip // open downloaded zip
int err; int err;
auto* za = zip_open(zipname.string().c_str(), ZIP_RDONLY, &err); auto* za = zip_open(zipname.string().c_str(), ZIP_RDONLY, &err);
@ -266,7 +277,7 @@ bool CemuUpdateWindow::ExtractUpdate(const fs::path& zipname, const fs::path& ta
} }
const auto count = zip_get_num_entries(za, 0); const auto count = zip_get_num_entries(za, 0);
m_gauge_max_value = count; m_gaugeMaxValue = count;
for (auto i = 0; i < count; i++) for (auto i = 0; i < count; i++)
{ {
if (m_order == WorkerOrder::Exit) if (m_order == WorkerOrder::Exit)
@ -297,6 +308,13 @@ bool CemuUpdateWindow::ExtractUpdate(const fs::path& zipname, const fs::path& ta
SystemException sys(ex); SystemException sys(ex);
forceLog_printf("can't create folder \"%s\" for update: %s", sb.name, sys.what()); forceLog_printf("can't create folder \"%s\" for update: %s", sb.name, sys.what());
} }
// the root should have only one Cemu_... directory, we track it here
if ((std::count(sb.name, sb.name + len, '/') + std::count(sb.name, sb.name + len, '\\')) == 1)
{
if (!cemuFolderName.empty())
forceLog_printf("update zip has multiple folders in root");
cemuFolderName.assign(sb.name, len-1);
}
continue; continue;
} }
@ -342,7 +360,7 @@ bool CemuUpdateWindow::ExtractUpdate(const fs::path& zipname, const fs::path& ta
} }
auto* event = new wxCommandEvent(wxEVT_PROGRESS); auto* event = new wxCommandEvent(wxEVT_PROGRESS);
event->SetInt(m_gauge_max_value); event->SetInt(m_gaugeMaxValue);
wxQueueEvent(this, event); wxQueueEvent(this, event);
zip_close(za); zip_close(za);
@ -372,7 +390,7 @@ void CemuUpdateWindow::WorkerThread()
if (m_order == WorkerOrder::CheckVersion) if (m_order == WorkerOrder::CheckVersion)
{ {
auto* event = new wxCommandEvent(wxEVT_RESULT); auto* event = new wxCommandEvent(wxEVT_RESULT);
if (GetServerVersion(m_version, m_filename, m_changelog_filename) && IsUpdateAvailable(m_version)) if (QueryUpdateInfo(m_downloadUrl, m_changelogUrl))
event->SetInt((int)Result::UpdateAvailable); event->SetInt((int)Result::UpdateAvailable);
else else
event->SetInt((int)Result::NoUpdateAvailable); event->SetInt((int)Result::NoUpdateAvailable);
@ -382,7 +400,7 @@ void CemuUpdateWindow::WorkerThread()
else if (m_order == WorkerOrder::UpdateVersion) else if (m_order == WorkerOrder::UpdateVersion)
{ {
// download update // download update
const std::string url = fmt::format("http://cemu.info/releases/{}", m_filename); const std::string url = m_downloadUrl;
if (!exists(tmppath)) if (!exists(tmppath))
create_directory(tmppath); create_directory(tmppath);
@ -405,8 +423,20 @@ void CemuUpdateWindow::WorkerThread()
break; break;
// extract // extract
const auto expected_path = (tmppath / m_filename).replace_extension(""); std::string cemuFolderName;
if (ExtractUpdate(update_file, tmppath) && exists(expected_path)) if (!ExtractUpdate(update_file, tmppath, cemuFolderName))
{
cemuLog_log(LogType::Force, "Extracting Cemu zip failed");
break;
}
if (cemuFolderName.empty())
{
cemuLog_log(LogType::Force, "Cemu folder not found in zip");
break;
}
const auto expected_path = tmppath / cemuFolderName;
if (exists(expected_path))
{ {
auto* event = new wxCommandEvent(wxEVT_RESULT); auto* event = new wxCommandEvent(wxEVT_RESULT);
event->SetInt((int)Result::ExtractSuccess); event->SetInt((int)Result::ExtractSuccess);
@ -446,7 +476,7 @@ void CemuUpdateWindow::WorkerThread()
const auto exec = ActiveSettings::GetFullPath(); const auto exec = ActiveSettings::GetFullPath();
const auto target_exe = fs::path(exec).replace_extension("exe.backup"); const auto target_exe = fs::path(exec).replace_extension("exe.backup");
fs::rename(exec, target_exe); fs::rename(exec, target_exe);
m_restart_file = exec; m_restartFile = exec;
const auto index = expected_path.wstring().size(); const auto index = expected_path.wstring().size();
int counter = 0; int counter = 0;
@ -484,7 +514,7 @@ void CemuUpdateWindow::WorkerThread()
} }
auto* event = new wxCommandEvent(wxEVT_PROGRESS); auto* event = new wxCommandEvent(wxEVT_PROGRESS);
event->SetInt(m_gauge_max_value); event->SetInt(m_gaugeMaxValue);
wxQueueEvent(this, event); wxQueueEvent(this, event);
auto* result_event = new wxCommandEvent(wxEVT_RESULT); auto* result_event = new wxCommandEvent(wxEVT_RESULT);
@ -515,7 +545,7 @@ void CemuUpdateWindow::OnClose(wxCloseEvent& event)
event.Skip(); event.Skip();
#if BOOST_OS_WINDOWS #if BOOST_OS_WINDOWS
if (m_restart_required && !m_restart_file.empty() && fs::exists(m_restart_file)) if (m_restartRequired && !m_restartFile.empty() && fs::exists(m_restartFile))
{ {
PROCESS_INFORMATION pi{}; PROCESS_INFORMATION pi{};
STARTUPINFO si{}; STARTUPINFO si{};
@ -524,7 +554,7 @@ void CemuUpdateWindow::OnClose(wxCloseEvent& event)
std::wstring cmdline = GetCommandLineW(); std::wstring cmdline = GetCommandLineW();
const auto index = cmdline.find('"', 1); const auto index = cmdline.find('"', 1);
cemu_assert_debug(index != std::wstring::npos); cemu_assert_debug(index != std::wstring::npos);
cmdline = L"\"" + m_restart_file.wstring() + L"\"" + cmdline.substr(index + 1); cmdline = L"\"" + m_restartFile.wstring() + L"\"" + cmdline.substr(index + 1);
HANDLE lock = CreateMutex(nullptr, TRUE, L"Global\\cemu_update_lock"); HANDLE lock = CreateMutex(nullptr, TRUE, L"Global\\cemu_update_lock");
CreateProcess(nullptr, (wchar_t*)cmdline.c_str(), nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi); CreateProcess(nullptr, (wchar_t*)cmdline.c_str(), nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi);
@ -542,25 +572,24 @@ void CemuUpdateWindow::OnResult(wxCommandEvent& event)
switch ((Result)event.GetInt()) switch ((Result)event.GetInt())
{ {
case Result::NoUpdateAvailable: case Result::NoUpdateAvailable:
m_cancel_button->SetLabel(_("Exit")); m_cancelButton->SetLabel(_("Exit"));
m_text->SetLabel(_("No update available!")); m_text->SetLabel(_("No update available!"));
m_gauge->SetValue(100); m_gauge->SetValue(100);
break; break;
case Result::UpdateAvailable: case Result::UpdateAvailable:
{ {
if (!m_changelog_filename.empty()) if (!m_changelogUrl.empty())
{ {
m_changelog->SetURL(fmt::format("https://cemu.info/changelog/{}", m_changelog_filename)); m_changelog->SetURL(m_changelogUrl);
m_changelog->Show(); m_changelog->Show();
} }
else else
m_changelog->Hide(); m_changelog->Hide();
m_update_button->Show(); m_updateButton->Show();
m_text->SetLabel(_("Update available!")); m_text->SetLabel(_("Update available!"));
m_cancel_button->SetLabel(_("Exit")); m_cancelButton->SetLabel(_("Exit"));
break; break;
} }
case Result::UpdateDownloaded: case Result::UpdateDownloaded:
@ -568,26 +597,26 @@ void CemuUpdateWindow::OnResult(wxCommandEvent& event)
m_gauge->SetValue(0); m_gauge->SetValue(0);
break; break;
case Result::UpdateDownloadError: case Result::UpdateDownloadError:
m_update_button->Enable(); m_updateButton->Enable();
m_text->SetLabel(_("Couldn't download the update!")); m_text->SetLabel(_("Couldn't download the update!"));
break; break;
case Result::ExtractSuccess: case Result::ExtractSuccess:
m_text->SetLabel(_("Applying update...")); m_text->SetLabel(_("Applying update..."));
m_gauge->SetValue(0); m_gauge->SetValue(0);
m_cancel_button->Disable(); m_cancelButton->Disable();
break; break;
case Result::ExtractError: case Result::ExtractError:
m_update_button->Enable(); m_updateButton->Enable();
m_cancel_button->Enable(); m_cancelButton->Enable();
m_text->SetLabel(_("Extracting failed!")); m_text->SetLabel(_("Extracting failed!"));
break; break;
case Result::Success: case Result::Success:
m_cancel_button->Enable(); m_cancelButton->Enable();
m_update_button->Hide(); m_updateButton->Hide();
m_text->SetLabel(_("Success")); m_text->SetLabel(_("Success"));
m_cancel_button->SetLabel(_("Restart")); m_cancelButton->SetLabel(_("Restart"));
m_restart_required = true; m_restartRequired = true;
break; break;
default: ; default: ;
} }
@ -595,7 +624,7 @@ void CemuUpdateWindow::OnResult(wxCommandEvent& event)
void CemuUpdateWindow::OnGaugeUpdate(wxCommandEvent& event) void CemuUpdateWindow::OnGaugeUpdate(wxCommandEvent& event)
{ {
const int total_size = m_gauge_max_value > 0 ? m_gauge_max_value : 10000000; const int total_size = m_gaugeMaxValue > 0 ? m_gaugeMaxValue : 10000000;
m_gauge->SetValue((event.GetInt() * 100) / total_size); m_gauge->SetValue((event.GetInt() * 100) / total_size);
} }
@ -606,7 +635,7 @@ void CemuUpdateWindow::OnUpdateButton(const wxCommandEvent& event)
m_condition.notify_all(); m_condition.notify_all();
m_update_button->Disable(); m_updateButton->Disable();
m_text->SetLabel(_("Downloading update...")); m_text->SetLabel(_("Downloading update..."));
} }

View file

@ -15,12 +15,12 @@ public:
CemuUpdateWindow(wxWindow* parent); CemuUpdateWindow(wxWindow* parent);
~CemuUpdateWindow(); ~CemuUpdateWindow();
static std::future<bool> IsUpdateAvailable(); static std::future<bool> IsUpdateAvailableAsync();
private: private:
wxStaticText* m_text; wxStaticText* m_text;
wxGauge* m_gauge; wxGauge* m_gauge;
wxButton* m_cancel_button, *m_update_button; wxButton* m_cancelButton, *m_updateButton;
wxHyperlinkCtrl* m_changelog; wxHyperlinkCtrl* m_changelog;
void OnUpdateButton(const wxCommandEvent& event); void OnUpdateButton(const wxCommandEvent& event);
@ -30,13 +30,12 @@ private:
void OnGaugeUpdate(wxCommandEvent& event); void OnGaugeUpdate(wxCommandEvent& event);
static size_t WriteStringCallback(char* ptr, size_t size, size_t nmemb, void* userdata); static size_t WriteStringCallback(char* ptr, size_t size, size_t nmemb, void* userdata);
static bool GetServerVersion(uint64& version, std::string& filename, std::string& changelog_filename); static bool QueryUpdateInfo(std::string& downloadUrlOut, std::string& changelogUrlOut);
static bool CheckVersion(); static bool CheckVersion();
static bool IsUpdateAvailable(uint64 latest_version);
static int ProgressCallback(void* clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow); static int ProgressCallback(void* clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow);
bool DownloadCemuZip(const std::string& url, const fs::path& filename); bool DownloadCemuZip(const std::string& url, const fs::path& filename);
bool ExtractUpdate(const fs::path& zipname, const fs::path& targetpath); bool ExtractUpdate(const fs::path& zipname, const fs::path& targetpath, std::string& cemuFolderName);
enum class WorkerOrder enum class WorkerOrder
{ {
@ -61,11 +60,10 @@ private:
WorkerOrder m_order = WorkerOrder::CheckVersion; WorkerOrder m_order = WorkerOrder::CheckVersion;
void WorkerThread(); void WorkerThread();
uint64 m_version = 0; std::string m_downloadUrl, m_changelogUrl;
std::string m_filename, m_changelog_filename; int m_gaugeMaxValue = 0;
int m_gauge_max_value = 0;
std::thread m_thread; std::thread m_thread;
fs::path m_restart_file; fs::path m_restartFile;
bool m_restart_required = false; bool m_restartRequired = false;
}; };

View file

@ -212,7 +212,7 @@ void ChecksumTool::LoadOnlineData() const
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl, CURLOPT_USERAGENT, fmt::format("Cemu_{}.{}{}", EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_SUFFIX).c_str()); curl_easy_setopt(curl, CURLOPT_USERAGENT, BUILD_VERSION_WITH_NAME_STRING);
curl_easy_perform(curl); curl_easy_perform(curl);
@ -248,7 +248,7 @@ void ChecksumTool::LoadOnlineData() const
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl, CURLOPT_USERAGENT, fmt::format("Cemu_{}.{}{}", EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_SUFFIX).c_str()); curl_easy_setopt(curl, CURLOPT_USERAGENT, BUILD_VERSION_WITH_NAME_STRING);
curl_easy_perform(curl); curl_easy_perform(curl);

View file

@ -54,9 +54,7 @@ bool DownloadGraphicPacksWindow::curlDownloadFile(const char *url, curlDownloadF
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
char temp[128]; curl_easy_setopt(curl, CURLOPT_USERAGENT, BUILD_VERSION_WITH_NAME_STRING);
sprintf(temp, "Cemu_%d.%d%s", EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_SUFFIX);
curl_easy_setopt(curl, CURLOPT_USERAGENT, temp);
downloadState->fileData.resize(0); downloadState->fileData.resize(0);
const CURLcode res = curl_easy_perform(curl); const CURLcode res = curl_easy_perform(curl);
curl_easy_cleanup(curl); curl_easy_cleanup(curl);

View file

@ -368,7 +368,7 @@ MainWindow::~MainWindow()
wxString MainWindow::GetInitialWindowTitle() wxString MainWindow::GetInitialWindowTitle()
{ {
return wxStringFormat2(EMULATOR_NAME" {}.{}{}", EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_SUFFIX); return BUILD_VERSION_WITH_NAME_STRING;
} }
void MainWindow::ShowGettingStartedDialog() void MainWindow::ShowGettingStartedDialog()
@ -798,7 +798,7 @@ void MainWindow::OpenSettings()
#endif #endif
if(config.check_update && !m_game_launched) if(config.check_update && !m_game_launched)
m_update_available = CemuUpdateWindow::IsUpdateAvailable(); m_update_available = CemuUpdateWindow::IsUpdateAvailableAsync();
if (mlc_modified) if (mlc_modified)
RecreateMenu(); RecreateMenu();
@ -1217,7 +1217,7 @@ void MainWindow::LoadSettings()
const auto& config = GetConfig(); const auto& config = GetConfig();
if(config.check_update) if(config.check_update)
m_update_available = CemuUpdateWindow::IsUpdateAvailable(); m_update_available = CemuUpdateWindow::IsUpdateAvailableAsync();
if (config.window_position != Vector2i{ -1,-1 }) if (config.window_position != Vector2i{ -1,-1 })
this->SetPosition({ config.window_position.x, config.window_position.y }); this->SetPosition({ config.window_position.x, config.window_position.y });
@ -1802,7 +1802,7 @@ public:
void AddHeaderInfo(wxWindow* parent, wxSizer* sizer) void AddHeaderInfo(wxWindow* parent, wxSizer* sizer)
{ {
char versionString[512]; char versionString[512];
sprintf(versionString, "Cemu\nVersion %d.%d\nCompiled " BUILD_DATE "\nOriginal authors: Exzap, Petergov", EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR); sprintf(versionString, "Cemu\nVersion %s\nCompiled " BUILD_DATE "\nOriginal authors: Exzap, Petergov", BUILD_VERSION_STRING);
sizer->Add(new wxStaticText(parent, wxID_ANY, versionString), wxSizerFlags().Border(wxALL, 3).Border(wxTOP, 10)); sizer->Add(new wxStaticText(parent, wxID_ANY, versionString), wxSizerFlags().Border(wxALL, 3).Border(wxTOP, 10));
sizer->Add(new wxHyperlinkCtrl(parent, -1, "https://cemu.info", "https://cemu.info"), wxSizerFlags().Expand().Border(wxTOP | wxBOTTOM, 3)); sizer->Add(new wxHyperlinkCtrl(parent, -1, "https://cemu.info", "https://cemu.info"), wxSizerFlags().Expand().Border(wxTOP | wxBOTTOM, 3));

View file

@ -47,7 +47,7 @@ WindowInfo& gui_getWindowInfo()
void gui_updateWindowTitles(bool isIdle, bool isLoading, double fps) void gui_updateWindowTitles(bool isIdle, bool isLoading, double fps)
{ {
std::string windowText; std::string windowText;
windowText = fmt::format("" EMULATOR_NAME " {}.{}{}", EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_SUFFIX); windowText = BUILD_VERSION_WITH_NAME_STRING;
if (isIdle) if (isIdle)
{ {

View file

@ -111,7 +111,7 @@ void checkForWine()
void infoLog_cemuStartup() void infoLog_cemuStartup()
{ {
cemuLog_force("------- Init {} {}.{}{} -------", EMULATOR_NAME, EMULATOR_VERSION_LEAD, EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_SUFFIX); cemuLog_force("------- Init {} -------", BUILD_VERSION_WITH_NAME_STRING);
cemuLog_force("Init Wii U memory space (base: 0x{:016x})", (size_t)memory_base); cemuLog_force("Init Wii U memory space (base: 0x{:016x})", (size_t)memory_base);
cemuLog_force(u8"mlc01 path: {}", ActiveSettings::GetMlcPath().generic_u8string()); cemuLog_force(u8"mlc01 path: {}", ActiveSettings::GetMlcPath().generic_u8string());
// check for wine version // check for wine version

Binary file not shown.