diff --git a/.github/workflows/win32.yml b/.github/workflows/win32.yml
index f5f1d11fc..b9cd7499e 100644
--- a/.github/workflows/win32.yml
+++ b/.github/workflows/win32.yml
@@ -27,14 +27,14 @@ jobs:
# Check-out repository under $GITHUB_WORKSPACE
# https://github.com/actions/checkout
- name: Check-out repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
submodules: true
# Discover location of MSBuild tool and to PATH environment variables
# https://github.com/microsoft/setup-msbuild
- name: Locate MSBuild
- uses: microsoft/setup-msbuild@v1.3.1
+ uses: microsoft/setup-msbuild@v2
# Use NuGet to download the latest libVLC.
- name: Download libVLC
@@ -98,7 +98,6 @@ jobs:
-DSDL2_LIBRARY=%SDL2_LIBRARY%
-DVLC_LIBRARIES=%VLC_LIBRARIES%
-DVLC_VERSION=%VLC_VERSION%
- -DCMAKE_EXE_LINKER_FLAGS=/SAFESEH:NO
# Use CMake to build project
- name: Build EmulationStation
@@ -130,7 +129,7 @@ jobs:
# Uploads artifacts from workflow
# https://github.com/actions/upload-artifact
- name: Upload artifacts
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: EmulationStation
path: |
diff --git a/README.md b/README.md
index 0f16f47a2..e91e771fe 100644
--- a/README.md
+++ b/README.md
@@ -158,8 +158,7 @@ C:\src\EmulationStation>cmake . -B build -A Win32 ^
-DCURL_LIBRARY=%CURL_LIBRARY% ^
-DSDL2_LIBRARY=%SDL2_LIBRARY% ^
-DVLC_LIBRARIES=%VLC_LIBRARIES% ^
--DVLC_VERSION=%VLC_VERSION% ^
--DCMAKE_EXE_LINKER_FLAGS=/SAFESEH:NO
+-DVLC_VERSION=%VLC_VERSION%
```
* Use CMake to build the Visual Studio project.
diff --git a/es-app/CMakeLists.txt b/es-app/CMakeLists.txt
index a828a462f..0c29f5c48 100644
--- a/es-app/CMakeLists.txt
+++ b/es-app/CMakeLists.txt
@@ -120,6 +120,7 @@ set(ES_SOURCES
if(MSVC)
LIST(APPEND ES_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/EmulationStation.rc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/EmulationStation.manifest
)
endif()
diff --git a/es-app/src/EmulationStation.manifest b/es-app/src/EmulationStation.manifest
new file mode 100644
index 000000000..36a689197
--- /dev/null
+++ b/es-app/src/EmulationStation.manifest
@@ -0,0 +1,9 @@
+
+
+
+
+ PerMonitorV2
+ UTF-8
+
+
+
diff --git a/es-app/src/FileData.cpp b/es-app/src/FileData.cpp
index 1aa4f0f07..38314dbeb 100644
--- a/es-app/src/FileData.cpp
+++ b/es-app/src/FileData.cpp
@@ -283,7 +283,9 @@ void FileData::launchGame(Window* window)
AudioManager::getInstance()->deinit();
VolumeControl::getInstance()->deinit();
InputManager::getInstance()->deinit();
+#ifndef _WIN32
window->deinit();
+#endif
std::string command = mEnvData->mLaunchCommand;
@@ -299,7 +301,7 @@ void FileData::launchGame(Window* window)
Scripting::fireEvent("game-start", rom, basename, name);
LOG(LogInfo) << " " << command;
- int exitCode = runSystemCommand(command);
+ int exitCode = launchGameCommand(command);
if(exitCode != 0)
{
@@ -308,7 +310,9 @@ void FileData::launchGame(Window* window)
Scripting::fireEvent("game-end");
+#ifndef _WIN32
window->init();
+#endif
InputManager::getInstance()->init();
VolumeControl::getInstance()->init();
window->normalizeNextUpdate();
diff --git a/es-app/src/guis/GuiMenu.cpp b/es-app/src/guis/GuiMenu.cpp
index b3150db4a..ed0666438 100644
--- a/es-app/src/guis/GuiMenu.cpp
+++ b/es-app/src/guis/GuiMenu.cpp
@@ -522,6 +522,7 @@ void GuiMenu::openQuitMenu()
ComponentListRow row;
if (UIModeController::getInstance()->isUIModeFull())
{
+#ifndef _WIN32
auto static restart_es_fx = []() {
Scripting::fireEvent("quit");
if (quitES(QuitMode::RESTART)) {
@@ -538,6 +539,7 @@ void GuiMenu::openQuitMenu()
}
row.addElement(std::make_shared(window, "RESTART EMULATIONSTATION", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true);
s->addRow(row);
+#endif
if(Settings::getInstance()->getBool("ShowExit"))
{
diff --git a/es-core/src/Scripting.cpp b/es-core/src/Scripting.cpp
index 19b7797a4..6cb67ff8d 100644
--- a/es-core/src/Scripting.cpp
+++ b/es-core/src/Scripting.cpp
@@ -30,12 +30,10 @@ namespace Scripting
for(std::list::const_iterator dirIt = scriptDirList.cbegin(); dirIt != scriptDirList.cend(); ++dirIt) {
std::list scripts = Utils::FileSystem::getDirContent(*dirIt);
for (std::list::const_iterator it = scripts.cbegin(); it != scripts.cend(); ++it) {
-#ifndef WIN32 // osx / linux
if (!Utils::FileSystem::isExecutable(*it)) {
LOG(LogWarning) << *it << " is not executable. Review file permissions.";
continue;
}
-#endif
std::string script = *it;
if (arg1.length() > 0) {
script += " \"" + arg1 + "\"";
diff --git a/es-core/src/components/VideoVlcComponent.cpp b/es-core/src/components/VideoVlcComponent.cpp
index 4ef7500d0..7ad0ca02b 100644
--- a/es-core/src/components/VideoVlcComponent.cpp
+++ b/es-core/src/components/VideoVlcComponent.cpp
@@ -7,7 +7,6 @@
#include "Settings.h"
#ifdef WIN32
#include
-#include
typedef SSIZE_T ssize_t;
#else
#include
diff --git a/es-core/src/platform.cpp b/es-core/src/platform.cpp
index dc904c49e..92dffd695 100644
--- a/es-core/src/platform.cpp
+++ b/es-core/src/platform.cpp
@@ -2,7 +2,9 @@
#include
#ifdef WIN32
-#include
+#include
+#include
+#include "renderers/Renderer.h"
#else
#include
#endif
@@ -30,15 +32,56 @@ int runRestartCommand()
int runSystemCommand(const std::string& cmd_utf8)
{
-#ifdef WIN32
- // on Windows we use _wsystem to support non-ASCII paths
- // which requires converting from utf8 to a wstring
- typedef std::codecvt_utf8 convert_type;
- std::wstring_convert converter;
- std::wstring wchar_str = converter.from_bytes(cmd_utf8);
- return _wsystem(wchar_str.c_str());
-#else
return system(cmd_utf8.c_str());
+}
+
+int launchGameCommand(const std::string& cmd_utf8)
+{
+#ifdef _WIN32
+ STARTUPINFO
+ si;
+ PROCESS_INFORMATION
+ pi;
+ SDL_Event
+ event;
+ DWORD
+ rcode = 0;
+ Uint32
+ wf;
+
+ wf = SDL_GetWindowFlags(Renderer::getSDLWindow());
+ SDL_SetWindowFullscreen(Renderer::getSDLWindow(), 0);
+ SDL_SetWindowBordered(Renderer::getSDLWindow(), SDL_TRUE);
+
+ Renderer::swapBuffers();
+
+ memset(&si, 0, sizeof si);
+ memset(&pi, 0, sizeof pi);
+ si.cb = sizeof si;
+
+ if(!CreateProcess(NULL, (LPSTR)cmd_utf8.c_str(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
+ return 9009;
+
+ while(WaitForSingleObject(pi.hProcess, 200) == WAIT_TIMEOUT)
+ while(SDL_PollEvent(&event))
+ ; // NOP
+
+ GetExitCodeProcess(pi.hProcess, &rcode);
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+
+ if(wf & SDL_WINDOW_FULLSCREEN)
+ SDL_SetWindowFullscreen(Renderer::getSDLWindow(), SDL_WINDOW_FULLSCREEN);
+ if(wf & SDL_WINDOW_BORDERLESS)
+ SDL_SetWindowBordered(Renderer::getSDLWindow(), SDL_FALSE);
+
+ wf = SDL_GetWindowFlags(Renderer::getSDLWindow());
+ if(wf & SDL_WINDOW_MINIMIZED)
+ SDL_RestoreWindow(Renderer::getSDLWindow());
+
+ return rcode;
+#else
+ return runSystemCommand(cmd_utf8);
#endif
}
@@ -57,9 +100,7 @@ int quitES(QuitMode mode)
void touch(const std::string& filename)
{
#ifdef WIN32
- FILE* fp = fopen(filename.c_str(), "ab+");
- if (fp != NULL)
- fclose(fp);
+ // Windows hasn't /tmp directory usualy so nothing to touch.
#else
int fd = open(filename.c_str(), O_CREAT|O_WRONLY, 0644);
if (fd >= 0)
diff --git a/es-core/src/platform.h b/es-core/src/platform.h
index 1df4d56c6..b774a07be 100644
--- a/es-core/src/platform.h
+++ b/es-core/src/platform.h
@@ -17,7 +17,8 @@ enum QuitMode
REBOOT = 3
};
-int runSystemCommand(const std::string& cmd_utf8); // run a utf-8 encoded in the shell (requires wstring conversion on Windows)
+int runSystemCommand(const std::string& cmd_utf8); // run a utf-8 encoded in the shell
+int launchGameCommand(const std::string& cmd_utf8);
int quitES(QuitMode mode = QuitMode::QUIT);
void processQuitMode();
diff --git a/es-core/src/utils/FileSystemUtil.cpp b/es-core/src/utils/FileSystemUtil.cpp
index 94be3a58b..50ff815b5 100644
--- a/es-core/src/utils/FileSystemUtil.cpp
+++ b/es-core/src/utils/FileSystemUtil.cpp
@@ -9,6 +9,7 @@
#if defined(_WIN32)
// because windows...
+#include "utils/StringUtil.h"
#include
#include
#define getcwd _getcwd
@@ -34,21 +35,6 @@ namespace Utils
static std::string exePath = "";
static std::map pathExistsIndex = std::map();
-//////////////////////////////////////////////////////////////////////////
-
-#if defined(_WIN32)
- static std::string convertFromWideString(const std::wstring _wstring)
- {
- const int numBytes = WideCharToMultiByte(CP_UTF8, 0, _wstring.c_str(), (int)_wstring.length(), nullptr, 0, nullptr, nullptr);
- std::string string(numBytes, 0);
-
- WideCharToMultiByte(CP_UTF8, 0, _wstring.c_str(), (int)_wstring.length(), (char*)string.c_str(), numBytes, nullptr, nullptr);
-
- return std::string(string);
-
- } // convertFromWideString
-#endif // _WIN32
-
//////////////////////////////////////////////////////////////////////////
stringList getDirContent(const std::string& _path, const bool _recursive)
@@ -62,16 +48,16 @@ namespace Utils
#if defined(_WIN32)
const std::unique_lock lock(mutex);
- WIN32_FIND_DATAW findData;
+ WIN32_FIND_DATA findData;
const std::string wildcard = path + "/*";
- const HANDLE hFind = FindFirstFileW(std::wstring(wildcard.begin(), wildcard.end()).c_str(), &findData);
+ const HANDLE hFind = FindFirstFile(wildcard.c_str(), &findData);
if(hFind != INVALID_HANDLE_VALUE)
{
// loop over all files in the directory
do
{
- const std::string name = convertFromWideString(findData.cFileName);
+ const std::string name = findData.cFileName;
// ignore "." and ".."
if((name != ".") && (name != ".."))
@@ -83,8 +69,10 @@ namespace Utils
if(_recursive && isDirectory(fullName))
contentList.merge(getDirContent(fullName, true));
}
+
+ FindNextFile(hFind, &findData);
}
- while(FindNextFileW(hFind, &findData));
+ while(GetLastError() != ERROR_NO_MORE_FILES);
FindClose(hFind);
}
@@ -216,13 +204,14 @@ namespace Utils
void setExePath(const std::string& _path)
{
const size_t path_max = 32767;
+ std::string result(path_max, 0);
#if defined(_WIN32)
- std::wstring result(path_max, 0);
- if(GetModuleFileNameW(nullptr, &result[0], path_max) != 0)
- exePath = convertFromWideString(result);
+ if(GetModuleFileName(nullptr, &result[0], path_max) != 0){
+ result.resize(result.find_first_of('\0'));
+ exePath = result;
+ }
#else // _WIN32
- std::string result(path_max, 0);
if(readlink("/proc/self/exe", &result[0], path_max) != -1)
exePath = result;
#endif // !_WIN32
@@ -570,9 +559,9 @@ namespace Utils
if(hFile != INVALID_HANDLE_VALUE)
{
resolved.resize(GetFinalPathNameByHandle(hFile, nullptr, 0, FILE_NAME_NORMALIZED) + 1);
- if(GetFinalPathNameByHandle(hFile, (LPSTR)resolved.data(), (DWORD)resolved.size(), FILE_NAME_NORMALIZED) > 0)
+ if(GetFinalPathNameByHandle(hFile, (LPSTR)resolved.data(), resolved.size(), FILE_NAME_NORMALIZED) > 0)
{
- resolved.resize(resolved.size() - 1);
+ resolved.resize(resolved.find_first_of('\0'));
resolved = getGenericPath(resolved);
}
CloseHandle(hFile);
@@ -606,7 +595,7 @@ namespace Utils
return true;
bool removed = (unlink(path.c_str()) == 0);
-
+
// if removed, let's remove it from the index
if (removed)
pathExistsIndex[_path] = false;
@@ -764,9 +753,19 @@ namespace Utils
//////////////////////////////////////////////////////////////////////////
-#if !defined(_WIN32)
bool isExecutable(const std::string& _path)
{
+#ifdef _WIN32
+ std::string ext = getenv("PATHEXT");
+ Utils::String::stringVector pathext = Utils::String::delimitedStringToVector(ext, ";");
+
+ ext = getExtension(_path);
+ for(auto it = pathext.cbegin(); it != pathext.cend(); it++)
+ if(stricmp(ext.c_str(), it->c_str()) == 0)
+ return true;
+
+ return false;
+#else
const std::string path = getGenericPath(_path);
// regular files and executables, but not setuid, setgid, shared text
@@ -780,9 +779,8 @@ namespace Utils
// check for mask attributes
return (info.st_mode & mask) == mask && (info.st_mode & mask_exec) != 0;
-
+#endif
} // isExecutable
-#endif // !_WIN32
} // FileSystem::
diff --git a/es-core/src/utils/FileSystemUtil.h b/es-core/src/utils/FileSystemUtil.h
index ac7a42384..cb950b1ab 100644
--- a/es-core/src/utils/FileSystemUtil.h
+++ b/es-core/src/utils/FileSystemUtil.h
@@ -39,9 +39,7 @@ namespace Utils
bool isDirectory (const std::string& _path);
bool isSymlink (const std::string& _path);
bool isHidden (const std::string& _path);
-#if !defined(_WIN32)
bool isExecutable (const std::string& _path);
-#endif // !_WIN32
} // FileSystem::