feat: implement override for GLFW/OpenAL with split natives

Fixes PrismLauncher/PrismLauncher#513

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
This commit is contained in:
Sefa Eyeoglu 2023-07-17 10:57:41 +02:00
parent 7ba1e7d356
commit ff67fd10c3
No known key found for this signature in database
GPG Key ID: E13DFD4B47127951
4 changed files with 68 additions and 7 deletions

View File

@ -16,6 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include <QDebug>
#include <QDir> #include <QDir>
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
@ -26,6 +27,15 @@
#include "Json.h" #include "Json.h"
#include "MangoHud.h" #include "MangoHud.h"
#ifdef __GLIBC__
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#define UNDEF_GNU_SOURCE
#endif
#include <dlfcn.h>
#include <linux/limits.h>
#endif
namespace MangoHud { namespace MangoHud {
QString getLibraryString() QString getLibraryString()
@ -106,4 +116,37 @@ QString getLibraryString()
return QString(); return QString();
} }
QString findLibrary(QString libName)
{
#ifdef __GLIBC__
const char* library = libName.toLocal8Bit().constData();
void* handle = dlopen(library, RTLD_NOW);
if (!handle) {
qCritical() << "dlopen() failed:" << dlerror();
return {};
}
char path[PATH_MAX];
if (dlinfo(handle, RTLD_DI_ORIGIN, path) == -1) {
qCritical() << "dlinfo() failed:" << dlerror();
dlclose(handle);
return {};
}
auto fullPath = FS::PathCombine(QString(path), libName);
dlclose(handle);
return fullPath;
#else
qWarning() << "MangoHud::findLibrary is not implemented on this platform";
return {};
#endif
}
} // namespace MangoHud } // namespace MangoHud
#ifdef UNDEF_GNU_SOURCE
#undef _GNU_SOURCE
#undef UNDEF_GNU_SOURCE
#endif

View File

@ -24,4 +24,6 @@
namespace MangoHud { namespace MangoHud {
QString getLibraryString(); QString getLibraryString();
}
QString findLibrary(QString libName);
} // namespace MangoHud

View File

@ -389,6 +389,24 @@ QStringList MinecraftInstance::extraArguments()
if (loaders.has_value() && loaders.value() & ResourceAPI::Quilt && settings()->get("DisableQuiltBeacon").toBool()) if (loaders.has_value() && loaders.value() & ResourceAPI::Quilt && settings()->get("DisableQuiltBeacon").toBool())
list.append("-Dloader.disable_beacon=true"); list.append("-Dloader.disable_beacon=true");
} }
#ifdef Q_OS_LINUX
{
QString openALPath;
QString glfwPath;
if (settings()->get("UseNativeOpenAL").toBool())
openALPath = MangoHud::findLibrary("libopenal.so");
if (settings()->get("UseNativeGLFW").toBool())
glfwPath = MangoHud::findLibrary("libglfw.so");
if (!openALPath.isEmpty())
list.append("-Dorg.lwjgl.openal.libname=" + openALPath);
if (!glfwPath.isEmpty())
list.append("-Dorg.lwjgl.glfw.libname=" + glfwPath);
}
#endif
return list; return list;
} }

View File

@ -39,7 +39,7 @@ static QString replaceSuffix(QString target, const QString& suffix, const QStrin
return target + replacement; return target + replacement;
} }
static bool unzipNatives(QString source, QString targetFolder, bool applyJnilibHack, bool nativeOpenAL, bool nativeGLFW) static bool unzipNatives(QString source, QString targetFolder, bool applyJnilibHack, bool nativeOpenAL)
{ {
QuaZip zip(source); QuaZip zip(source);
if (!zip.open(QuaZip::mdUnzip)) { if (!zip.open(QuaZip::mdUnzip)) {
@ -52,9 +52,6 @@ static bool unzipNatives(QString source, QString targetFolder, bool applyJnilibH
do { do {
QString name = zip.getCurrentFileName(); QString name = zip.getCurrentFileName();
auto lowercase = name.toLower(); auto lowercase = name.toLower();
if (nativeGLFW && name.contains("glfw")) {
continue;
}
if (nativeOpenAL && name.contains("openal")) { if (nativeOpenAL && name.contains("openal")) {
continue; continue;
} }
@ -83,14 +80,15 @@ void ExtractNatives::executeTask()
return; return;
} }
auto settings = minecraftInstance->settings(); auto settings = minecraftInstance->settings();
// We only need OpenAL here, as modern versions of LWJGL (3+) are handled by JVM args, while older versions (2) didn't have GLFW
bool nativeOpenAL = settings->get("UseNativeOpenAL").toBool(); bool nativeOpenAL = settings->get("UseNativeOpenAL").toBool();
bool nativeGLFW = settings->get("UseNativeGLFW").toBool();
auto outputPath = minecraftInstance->getNativePath(); auto outputPath = minecraftInstance->getNativePath();
auto javaVersion = minecraftInstance->getJavaVersion(); auto javaVersion = minecraftInstance->getJavaVersion();
bool jniHackEnabled = javaVersion.major() >= 8; bool jniHackEnabled = javaVersion.major() >= 8;
for (const auto& source : toExtract) { for (const auto& source : toExtract) {
if (!unzipNatives(source, outputPath, jniHackEnabled, nativeOpenAL, nativeGLFW)) { if (!unzipNatives(source, outputPath, jniHackEnabled, nativeOpenAL)) {
const char* reason = QT_TR_NOOP("Couldn't extract native jar '%1' to destination '%2'"); const char* reason = QT_TR_NOOP("Couldn't extract native jar '%1' to destination '%2'");
emit logLine(QString(reason).arg(source, outputPath), MessageLevel::Fatal); emit logLine(QString(reason).arg(source, outputPath), MessageLevel::Fatal);
emitFailed(tr(reason).arg(source, outputPath)); emitFailed(tr(reason).arg(source, outputPath));