mirror of https://github.com/xemu-project/xemu.git
Merge branch 'master' into DeviceEmulation-SteelBattalionController
This commit is contained in:
commit
720f06345c
|
@ -174,25 +174,25 @@ jobs:
|
|||
build_param: --debug
|
||||
artifact_name: xemu-ubuntu-x86_64-debug
|
||||
artifact_filename: xemu-ubuntu-x86_64-debug.tgz
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
- arch: x86_64
|
||||
configuration: Release
|
||||
build_param:
|
||||
artifact_name: xemu-ubuntu-x86_64-release
|
||||
artifact_filename: xemu-ubuntu-x86_64-release.tgz
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
- arch: aarch64
|
||||
configuration: Debug
|
||||
build_param: --debug
|
||||
artifact_name: xemu-ubuntu-aarch64-debug
|
||||
artifact_filename: xemu-ubuntu-aarch64-debug.tgz
|
||||
runs-on: ubuntu-24.04-arm
|
||||
runs-on: ubuntu-22.04-arm
|
||||
- arch: aarch64
|
||||
configuration: Release
|
||||
build_param:
|
||||
artifact_name: xemu-ubuntu-aarch64-release
|
||||
artifact_filename: xemu-ubuntu-aarch64-release.tgz
|
||||
runs-on: ubuntu-24.04-arm
|
||||
runs-on: ubuntu-22.04-arm
|
||||
steps:
|
||||
- name: Initialize compiler cache
|
||||
id: cache
|
||||
|
|
|
@ -17,7 +17,7 @@ jobs:
|
|||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@bd01e18f51369d5a26f1651c3cb451d3417e3bba # v6
|
||||
uses: astral-sh/setup-uv@7edac99f961f18b581bbd960d59d049f04c0002f # v6
|
||||
with:
|
||||
enable-cache: false
|
||||
|
||||
|
|
|
@ -360,6 +360,9 @@ display:
|
|||
advanced_tree_state:
|
||||
type: bool
|
||||
default: false
|
||||
setup_nvidia_profile:
|
||||
type: bool
|
||||
default: true
|
||||
|
||||
audio:
|
||||
vp:
|
||||
|
|
|
@ -223,9 +223,9 @@ unsigned int pgraph_gl_bind_inline_array(NV2AState *d)
|
|||
|
||||
nv2a_profile_inc_counter(NV2A_PROF_GEOM_BUFFER_UPDATE_2);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, r->gl_inline_array_buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, NV2A_MAX_BATCH_LENGTH * sizeof(uint32_t),
|
||||
NULL, GL_STREAM_DRAW);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, index_count * vertex_size, pg->inline_array);
|
||||
GLsizeiptr buffer_size = index_count * vertex_size;
|
||||
glBufferData(GL_ARRAY_BUFFER, buffer_size, NULL, GL_STREAM_DRAW);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, buffer_size, pg->inline_array);
|
||||
pgraph_gl_bind_vertex_attributes(d, 0, index_count-1, true, vertex_size,
|
||||
index_count-1);
|
||||
|
||||
|
@ -308,4 +308,4 @@ void pgraph_gl_finalize_buffers(PGRAPHState *pg)
|
|||
|
||||
glDeleteVertexArrays(1, &r->gl_vertex_array);
|
||||
r->gl_vertex_array = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,367 +13,517 @@ import os.path
|
|||
import re
|
||||
import sys
|
||||
|
||||
gplv2 = 'gplv2'
|
||||
mit = 'mit'
|
||||
bsd = 'bsd'
|
||||
bsd_2clause = 'bsd-2clause'
|
||||
bsd_3clause = 'bsd-3clause'
|
||||
zlib = 'zlib'
|
||||
lgplv2_1 = 'lgplv2_1'
|
||||
apache2 = 'apache2'
|
||||
unlicense = 'unlicense'
|
||||
multi = 'multi'
|
||||
gplv2 = "gplv2"
|
||||
mit = "mit"
|
||||
bsd = "bsd"
|
||||
bsd_2clause = "bsd-2clause"
|
||||
bsd_3clause = "bsd-3clause"
|
||||
zlib = "zlib"
|
||||
lgplv2_1 = "lgplv2_1"
|
||||
apache2 = "apache2"
|
||||
unlicense = "unlicense"
|
||||
multi = "multi"
|
||||
|
||||
|
||||
windows = 'windows'
|
||||
macos = 'darwin'
|
||||
linux = 'linux'
|
||||
all_platforms = { windows, macos, linux }
|
||||
windows = "windows"
|
||||
macos = "darwin"
|
||||
linux = "linux"
|
||||
all_platforms = {windows, macos, linux}
|
||||
current_platform = linux
|
||||
|
||||
versions = {}
|
||||
|
||||
|
||||
def banner(s):
|
||||
space = 1
|
||||
width = 80
|
||||
mid_len = 2*space+len(s)
|
||||
left_dashes = (width-mid_len)//2
|
||||
right_dashes = width-mid_len-left_dashes
|
||||
return '-'*left_dashes + ' ' + s + ' ' + '-'*right_dashes
|
||||
space = 1
|
||||
width = 80
|
||||
mid_len = 2 * space + len(s)
|
||||
left_dashes = (width - mid_len) // 2
|
||||
right_dashes = width - mid_len - left_dashes
|
||||
return "-" * left_dashes + " " + s + " " + "-" * right_dashes
|
||||
|
||||
|
||||
class Lib:
|
||||
def __init__(self, name, url,
|
||||
license, license_url, license_lines=None,
|
||||
submodule=None,
|
||||
version=None,
|
||||
ships_static=set(), ships_dynamic=set(),
|
||||
platform=all_platforms, pkgconfig=None,
|
||||
pkg_win=None, pkg_mac=None, pkg_ubuntu=None):
|
||||
self.name = name
|
||||
self.url = url
|
||||
self.license = license
|
||||
self.license_url = license_url
|
||||
self.license_lines = license_lines
|
||||
self.submodule = submodule
|
||||
self._version = version
|
||||
self.ships_static = ships_static
|
||||
self.ships_dynamic = ships_dynamic
|
||||
self.platform = platform
|
||||
self.pkgconfig = pkgconfig
|
||||
self.pkg_win = pkg_win
|
||||
self.pkg_mac = pkg_mac
|
||||
self.pkg_ubuntu = pkg_ubuntu
|
||||
def __init__(
|
||||
self,
|
||||
name,
|
||||
url,
|
||||
license,
|
||||
license_url=None,
|
||||
license_path=None,
|
||||
license_lines=None,
|
||||
submodule=None,
|
||||
version=None,
|
||||
ships_static=set(),
|
||||
ships_dynamic=set(),
|
||||
platform=all_platforms,
|
||||
pkgconfig=None,
|
||||
pkg_win=None,
|
||||
pkg_mac=None,
|
||||
pkg_ubuntu=None,
|
||||
):
|
||||
self.name = name
|
||||
self.url = url
|
||||
self.license = license
|
||||
self.license_url = license_url
|
||||
self.license_path = license_path or os.path.join(
|
||||
"licenses", self.name + ".license.txt"
|
||||
)
|
||||
self.license_lines = license_lines
|
||||
self.submodule = submodule
|
||||
self._version = version
|
||||
self.ships_static = ships_static
|
||||
self.ships_dynamic = ships_dynamic
|
||||
self.platform = platform
|
||||
self.pkgconfig = pkgconfig
|
||||
self.pkg_win = pkg_win
|
||||
self.pkg_mac = pkg_mac
|
||||
self.pkg_ubuntu = pkg_ubuntu
|
||||
|
||||
@property
|
||||
def version(self):
|
||||
if self._version:
|
||||
return self._version
|
||||
@property
|
||||
def version(self):
|
||||
if self._version:
|
||||
return self._version
|
||||
|
||||
if self.submodule:
|
||||
self._version = self.submodule.head
|
||||
return self._version
|
||||
if self.submodule:
|
||||
self._version = self.submodule.head
|
||||
return self._version
|
||||
|
||||
if self.pkgconfig:
|
||||
self._version = self.pkgconfig.modversion
|
||||
return self._version
|
||||
if self.pkgconfig:
|
||||
self._version = self.pkgconfig.modversion
|
||||
return self._version
|
||||
|
||||
if current_platform == windows and self.pkg_win:
|
||||
self._version = subprocess.run(r"grep -e '_VERSION\s*:=' /opt/mxe/src/" + self.pkg_win + ".mk | cut -d'=' -f2",
|
||||
capture_output=True, shell=True,
|
||||
check=True).stdout.decode('utf-8').strip()
|
||||
return self._version
|
||||
elif current_platform == macos and self.pkg_mac:
|
||||
self._version = versions[self.pkg_mac]
|
||||
return self._version
|
||||
elif current_platform == linux and self.pkg_ubuntu:
|
||||
self._version = subprocess.run(r"dpkg -s " + self.pkg_ubuntu + " | grep Version | cut -d: -f2",
|
||||
capture_output=True, shell=True,
|
||||
check=True).stdout.decode('utf-8').strip()
|
||||
return self._version
|
||||
if current_platform == windows and self.pkg_win:
|
||||
self._version = (
|
||||
subprocess.run(
|
||||
r"grep -e '_VERSION\s*:=' /opt/mxe/src/"
|
||||
+ self.pkg_win
|
||||
+ ".mk | cut -d'=' -f2",
|
||||
capture_output=True,
|
||||
shell=True,
|
||||
check=True,
|
||||
)
|
||||
.stdout.decode("utf-8")
|
||||
.strip()
|
||||
)
|
||||
return self._version
|
||||
elif current_platform == macos and self.pkg_mac:
|
||||
self._version = versions[self.pkg_mac]
|
||||
return self._version
|
||||
elif current_platform == linux and self.pkg_ubuntu:
|
||||
self._version = (
|
||||
subprocess.run(
|
||||
r"dpkg -s " + self.pkg_ubuntu + " | grep Version | cut -d: -f2",
|
||||
capture_output=True,
|
||||
shell=True,
|
||||
check=True,
|
||||
)
|
||||
.stdout.decode("utf-8")
|
||||
.strip()
|
||||
)
|
||||
return self._version
|
||||
|
||||
assert False, 'Failed to get version info for ' + self.name
|
||||
assert False, "Failed to get version info for " + self.name
|
||||
|
||||
@property
|
||||
def license_text(self):
|
||||
fname = os.path.join('licenses', self.name + '.license.txt')
|
||||
if os.path.exists(fname):
|
||||
with open(fname, 'r', encoding='utf-8') as f:
|
||||
return f.read()
|
||||
import requests
|
||||
d = requests.get(self.license_url).content.decode('utf-8')
|
||||
if self.license_lines:
|
||||
start, end = self.license_lines
|
||||
d = '\n'.join(d.splitlines()[start-1:end+1])
|
||||
with open(fname, 'w') as f:
|
||||
f.write(d)
|
||||
return d
|
||||
@property
|
||||
def license_text(self):
|
||||
if os.path.exists(self.license_path):
|
||||
with open(self.license_path, "r", encoding="utf-8") as f:
|
||||
return f.read()
|
||||
import requests
|
||||
|
||||
@property
|
||||
def is_active(self):
|
||||
return current_platform in self.platform
|
||||
d = requests.get(self.license_url).content.decode("utf-8")
|
||||
if self.license_lines:
|
||||
start, end = self.license_lines
|
||||
d = "\n".join(d.splitlines()[start - 1 : end + 1])
|
||||
with open(fname, "w") as f:
|
||||
f.write(d)
|
||||
return d
|
||||
|
||||
@property
|
||||
def does_ship_static(self):
|
||||
return current_platform in self.ships_static
|
||||
@property
|
||||
def is_active(self):
|
||||
return current_platform in self.platform
|
||||
|
||||
@property
|
||||
def does_ship_dynamic(self):
|
||||
return current_platform in self.ships_dynamic
|
||||
@property
|
||||
def does_ship_static(self):
|
||||
return current_platform in self.ships_static
|
||||
|
||||
@property
|
||||
def does_ship(self):
|
||||
return self.is_active and (self.does_ship_static or self.does_ship_dynamic)
|
||||
@property
|
||||
def does_ship_dynamic(self):
|
||||
return current_platform in self.ships_dynamic
|
||||
|
||||
@property
|
||||
def does_ship(self):
|
||||
return self.is_active and (self.does_ship_static or self.does_ship_dynamic)
|
||||
|
||||
|
||||
class PkgConfig:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
@property
|
||||
def modversion(self):
|
||||
pkg_config = {
|
||||
linux: "pkg-config",
|
||||
windows: "x86_64-w64-mingw32.static-pkg-config",
|
||||
macos: "pkg-config",
|
||||
}[current_platform]
|
||||
ver = subprocess.run(
|
||||
[pkg_config, "--modversion", self.name], capture_output=True, check=True
|
||||
)
|
||||
return ver.stdout.decode("utf-8").strip()
|
||||
|
||||
@property
|
||||
def modversion(self):
|
||||
pkg_config = {
|
||||
linux: 'pkg-config',
|
||||
windows: 'x86_64-w64-mingw32.static-pkg-config',
|
||||
macos: 'pkg-config',
|
||||
}[current_platform]
|
||||
ver = subprocess.run([pkg_config, '--modversion', self.name],
|
||||
capture_output=True, check=True)
|
||||
return ver.stdout.decode('utf-8').strip()
|
||||
|
||||
class Submodule:
|
||||
def __init__(self, path):
|
||||
self.path = path
|
||||
def __init__(self, path):
|
||||
self.path = path
|
||||
|
||||
@property
|
||||
def head(self):
|
||||
if self.path.endswith(".wrap"):
|
||||
with open(self.path, "r", encoding="utf-8") as file:
|
||||
contents = file.read()
|
||||
revision = re.search(r"^revision\s*=\s*(.*)", contents, re.MULTILINE)
|
||||
if revision:
|
||||
return revision.group(1)
|
||||
wrapdb_version = re.search(r"^wrapdb_version\s*=\s*([^-]*)", contents, re.MULTILINE)
|
||||
if wrapdb_version:
|
||||
return wrapdb_version.group(1)
|
||||
assert False, "revision not found for subproject"
|
||||
@property
|
||||
def head(self):
|
||||
if self.path.endswith(".wrap"):
|
||||
with open(self.path, "r", encoding="utf-8") as file:
|
||||
contents = file.read()
|
||||
revision = re.search(r"^revision\s*=\s*(.*)", contents, re.MULTILINE)
|
||||
if revision:
|
||||
return revision.group(1)
|
||||
wrapdb_version = re.search(
|
||||
r"^wrapdb_version\s*=\s*([^-]*)", contents, re.MULTILINE
|
||||
)
|
||||
if wrapdb_version:
|
||||
return wrapdb_version.group(1)
|
||||
assert False, "revision not found for subproject"
|
||||
|
||||
try:
|
||||
return subprocess.run(['git', 'rev-parse', 'HEAD'],
|
||||
cwd=self.path, capture_output=True,
|
||||
check=True).stdout.decode('utf-8').strip()
|
||||
except subprocess.CalledProcessError:
|
||||
pass
|
||||
try:
|
||||
return (
|
||||
subprocess.run(
|
||||
["git", "rev-parse", "HEAD"],
|
||||
cwd=self.path,
|
||||
capture_output=True,
|
||||
check=True,
|
||||
)
|
||||
.stdout.decode("utf-8")
|
||||
.strip()
|
||||
)
|
||||
except subprocess.CalledProcessError:
|
||||
pass
|
||||
|
||||
commit_file_path = os.path.join(self.path, 'HEAD')
|
||||
if os.path.exists(commit_file_path):
|
||||
return open(commit_file_path).read().strip()
|
||||
commit_file_path = os.path.join(self.path, "HEAD")
|
||||
if os.path.exists(commit_file_path):
|
||||
return open(commit_file_path).read().strip()
|
||||
|
||||
raise Exception("Failed to determine submodule revision")
|
||||
return ""
|
||||
|
||||
raise Exception('Failed to determine submodule revision')
|
||||
return ''
|
||||
|
||||
LIBS = [
|
||||
|
||||
Lib('qemu', 'https://www.qemu.org/',
|
||||
gplv2, 'https://raw.githubusercontent.com/xemu-project/xemu/master/LICENSE',
|
||||
version='6.0.0'
|
||||
),
|
||||
|
||||
#
|
||||
# Built from source with xemu
|
||||
#
|
||||
|
||||
Lib('slirp', 'https://gitlab.freedesktop.org/slirp',
|
||||
bsd_3clause, 'https://gitlab.freedesktop.org/slirp/libslirp/-/raw/master/COPYRIGHT', license_lines=(16,39),
|
||||
ships_static=all_platforms,
|
||||
pkgconfig=PkgConfig('slirp'), pkg_win='libslirp', pkg_mac='libslirp', pkg_ubuntu='libslirp-dev'
|
||||
),
|
||||
|
||||
Lib('imgui', 'https://github.com/ocornut/imgui',
|
||||
mit, 'https://raw.githubusercontent.com/ocornut/imgui/master/LICENSE.txt',
|
||||
ships_static=all_platforms,
|
||||
submodule=Submodule('subprojects/imgui.wrap')
|
||||
),
|
||||
|
||||
Lib('implot', 'https://github.com/epezent/implot',
|
||||
mit, 'https://raw.githubusercontent.com/epezent/implot/master/LICENSE',
|
||||
ships_static=all_platforms,
|
||||
submodule=Submodule('subprojects/implot.wrap')
|
||||
),
|
||||
|
||||
Lib('noc', 'https://github.com/guillaumechereau/noc/blob/master/noc_file_dialog.h',
|
||||
mit, 'https://raw.githubusercontent.com/xemu-project/xemu/master/ui/noc_file_dialog.h', license_lines=(1,22),
|
||||
ships_static=all_platforms,
|
||||
version='78b2e7b22506429dd1755ffff197c7da11507fd9'
|
||||
),
|
||||
|
||||
Lib('stb_image', 'https://github.com/nothings/stb',
|
||||
mit, 'https://raw.githubusercontent.com/nothings/stb/master/LICENSE', license_lines=(4,19),
|
||||
ships_static=all_platforms,
|
||||
version='2.25'
|
||||
),
|
||||
|
||||
Lib('tomlplusplus', 'https://github.com/marzer/tomlplusplus',
|
||||
mit, 'https://raw.githubusercontent.com/marzer/tomlplusplus/master/LICENSE',
|
||||
ships_static=all_platforms,
|
||||
submodule=Submodule('subprojects/tomlplusplus.wrap')
|
||||
),
|
||||
|
||||
Lib('xxHash', 'https://github.com/Cyan4973/xxHash.git',
|
||||
bsd, 'https://raw.githubusercontent.com/Cyan4973/xxHash/dev/LICENSE', license_lines=(1,26),
|
||||
ships_static=all_platforms,
|
||||
submodule=Submodule('subprojects/xxhash.wrap')
|
||||
),
|
||||
|
||||
Lib('fpng', 'https://github.com/richgel999/fpng',
|
||||
unlicense, 'https://github.com/richgel999/fpng/blob/main/README.md',
|
||||
ships_static=all_platforms,
|
||||
version='6926f5a0a78f22d42b074a0ab8032e07736babd4'
|
||||
),
|
||||
|
||||
Lib('nv2a_vsh_cpu', 'https://github.com/xemu-project/nv2a_vsh_cpu',
|
||||
unlicense, 'https://raw.githubusercontent.com/xemu-project/nv2a_vsh_cpu/main/LICENSE',
|
||||
ships_static=all_platforms,
|
||||
submodule=Submodule('subprojects/nv2a_vsh_cpu.wrap')
|
||||
),
|
||||
|
||||
Lib('volk', 'https://github.com/zeux/volk',
|
||||
mit, 'https://raw.githubusercontent.com/zeux/volk/master/LICENSE.md',
|
||||
ships_static=all_platforms,
|
||||
submodule=Submodule('subprojects/volk.wrap')
|
||||
),
|
||||
|
||||
Lib('VulkanMemoryAllocator', 'https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator',
|
||||
mit, 'https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator/master/LICENSE.txt',
|
||||
ships_static=all_platforms,
|
||||
submodule=Submodule('subprojects/VulkanMemoryAllocator.wrap')
|
||||
),
|
||||
|
||||
Lib('SPIRV-Reflect', 'https://github.com/KhronosGroup/SPIRV-Reflect',
|
||||
apache2, 'https://raw.githubusercontent.com/KhronosGroup/SPIRV-Reflect/main/LICENSE',
|
||||
ships_static=all_platforms,
|
||||
submodule=Submodule('subprojects/SPIRV-Reflect.wrap')
|
||||
),
|
||||
|
||||
Lib('glslang', 'https://github.com/KhronosGroup/glslang',
|
||||
bsd_3clause, 'https://raw.githubusercontent.com/KhronosGroup/glslang/main/LICENSE.txt',
|
||||
ships_static=all_platforms,
|
||||
submodule=Submodule('subprojects/glslang.wrap')
|
||||
),
|
||||
|
||||
#
|
||||
# Data files included with xemu
|
||||
#
|
||||
|
||||
Lib('roboto', 'https://github.com/googlefonts/roboto',
|
||||
apache2, 'https://raw.githubusercontent.com/googlefonts/roboto/main/LICENSE',
|
||||
ships_static=all_platforms,
|
||||
version='2.138'
|
||||
),
|
||||
|
||||
Lib('fontawesome', 'https://fontawesome.com',
|
||||
multi, '',
|
||||
ships_static=all_platforms,
|
||||
version='6.1.1'
|
||||
),
|
||||
|
||||
#
|
||||
# Libraries either linked statically, dynamically linked & shipped, or dynamically linked with system-installed libraries only
|
||||
#
|
||||
|
||||
Lib('sdl2', 'https://www.libsdl.org/',
|
||||
zlib, 'https://raw.githubusercontent.com/libsdl-org/SDL/main/LICENSE.txt',
|
||||
ships_static={windows}, ships_dynamic={macos},
|
||||
pkgconfig=PkgConfig('sdl2'), pkg_win='sdl2', pkg_mac='sdl2', pkg_ubuntu='libsdl2-dev'
|
||||
),
|
||||
|
||||
Lib('glib-2.0', 'https://gitlab.gnome.org/GNOME/glib',
|
||||
lgplv2_1, 'https://gitlab.gnome.org/GNOME/glib/-/raw/master/COPYING',
|
||||
ships_static={windows}, ships_dynamic={macos},
|
||||
pkgconfig=PkgConfig('glib-2.0'), pkg_win='glib', pkg_mac='glib', pkg_ubuntu='libglib2.0-dev'
|
||||
),
|
||||
|
||||
# glib dep
|
||||
Lib('pcre', 'http://pcre.org/',
|
||||
bsd, 'http://www.pcre.org/original/license.txt',
|
||||
pkgconfig=PkgConfig('libpcre'), pkg_ubuntu='libpcre3-dev'
|
||||
),
|
||||
Lib('pcre2', 'http://pcre.org/',
|
||||
bsd, 'https://www.pcre.org/licence.txt',
|
||||
ships_static={windows}, ships_dynamic={macos},
|
||||
pkgconfig=PkgConfig('libpcre2-8'), pkg_win='pcre2', pkg_mac='pcre2', pkg_ubuntu='libpcre2-dev'
|
||||
),
|
||||
|
||||
# glib dep
|
||||
Lib('gettext', 'https://www.gnu.org/software/gettext/',
|
||||
lgplv2_1, 'https://git.savannah.gnu.org/gitweb/?p=gettext.git;a=blob_plain;f=gettext-runtime/intl/COPYING.LIB;hb=HEAD',
|
||||
ships_static={windows}, ships_dynamic={macos},
|
||||
pkg_win='gettext', pkg_mac='gettext-runtime',
|
||||
),
|
||||
|
||||
# glib dep
|
||||
Lib('iconv', 'https://www.gnu.org/software/libiconv/',
|
||||
lgplv2_1, 'https://git.savannah.gnu.org/gitweb/?p=libiconv.git;a=blob_plain;f=COPYING.LIB;hb=HEAD',
|
||||
ships_static={windows}, ships_dynamic={macos},
|
||||
pkg_win='libiconv', pkg_mac='libiconv'
|
||||
),
|
||||
|
||||
Lib('libepoxy', 'https://github.com/anholt/libepoxy',
|
||||
mit, 'https://raw.githubusercontent.com/anholt/libepoxy/master/COPYING',
|
||||
ships_static={windows}, ships_dynamic={macos},
|
||||
pkgconfig=PkgConfig('epoxy'), pkg_win='libepoxy', pkg_mac='libepoxy', pkg_ubuntu='libepoxy-dev'
|
||||
),
|
||||
|
||||
Lib('pixman', 'http://www.pixman.org/',
|
||||
mit, 'https://cgit.freedesktop.org/pixman/plain/COPYING',
|
||||
ships_static={windows}, ships_dynamic={macos},
|
||||
pkgconfig=PkgConfig('pixman-1'),
|
||||
pkg_win='pixman',
|
||||
pkg_mac='pixman',
|
||||
pkg_ubuntu='libpixman-1-dev'
|
||||
),
|
||||
|
||||
Lib('libsamplerate', 'https://github.com/libsndfile/libsamplerate',
|
||||
bsd_2clause, 'https://raw.githubusercontent.com/libsndfile/libsamplerate/master/COPYING',
|
||||
ships_static={windows}, ships_dynamic={macos},
|
||||
pkgconfig=PkgConfig('samplerate'),
|
||||
pkg_win='libsamplerate',
|
||||
pkg_mac='libsamplerate',
|
||||
),
|
||||
|
||||
Lib('zlib', 'https://zlib.net/',
|
||||
zlib, 'https://raw.githubusercontent.com/madler/zlib/master/README', license_lines=(87,106),
|
||||
ships_static={windows}, ships_dynamic={macos},
|
||||
pkgconfig=PkgConfig('zlib'), pkg_win='zlib', pkg_mac='zlib', pkg_ubuntu='zlib1g-dev'
|
||||
),
|
||||
|
||||
Lib('libmingw32', 'http://mingw-w64.org/',
|
||||
multi, 'https://sourceforge.net/p/mingw-w64/mingw-w64/ci/master/tree/COPYING.MinGW-w64-runtime/COPYING.MinGW-w64-runtime.txt?format=raw',
|
||||
ships_static={windows}, platform={windows},
|
||||
pkg_win='mingw-w64',
|
||||
),
|
||||
|
||||
Lib('gtk', 'https://www.gtk.org/',
|
||||
lgplv2_1, 'https://gitlab.gnome.org/GNOME/gtk/-/raw/master/COPYING',
|
||||
platform={linux},
|
||||
pkgconfig=PkgConfig('gtk+-3.0'), pkg_ubuntu='libgtk-3-dev'
|
||||
),
|
||||
|
||||
Lib('miniz', 'https://github.com/richgel999/miniz',
|
||||
lgplv2_1, 'https://raw.githubusercontent.com/richgel999/miniz/master/LICENSE',
|
||||
ships_static={windows}, platform={windows},
|
||||
version='2.1.0'
|
||||
),
|
||||
|
||||
Lib('libcurl', 'https://curl.se/',
|
||||
mit, 'https://raw.githubusercontent.com/curl/curl/refs/heads/master/COPYING',
|
||||
ships_static={windows}, platform={windows},
|
||||
submodule=Submodule('subprojects/curl.wrap')
|
||||
),
|
||||
Lib(
|
||||
"qemu",
|
||||
"https://www.qemu.org/",
|
||||
gplv2,
|
||||
"https://raw.githubusercontent.com/xemu-project/xemu/master/LICENSE",
|
||||
version="6.0.0",
|
||||
),
|
||||
#
|
||||
# Built from source with xemu
|
||||
#
|
||||
Lib(
|
||||
"slirp",
|
||||
"https://gitlab.freedesktop.org/slirp",
|
||||
bsd_3clause,
|
||||
"https://gitlab.freedesktop.org/slirp/libslirp/-/raw/master/COPYRIGHT",
|
||||
license_lines=(16, 39),
|
||||
ships_static=all_platforms,
|
||||
pkgconfig=PkgConfig("slirp"),
|
||||
pkg_win="libslirp",
|
||||
pkg_mac="libslirp",
|
||||
pkg_ubuntu="libslirp-dev",
|
||||
),
|
||||
Lib(
|
||||
"imgui",
|
||||
"https://github.com/ocornut/imgui",
|
||||
mit,
|
||||
"https://raw.githubusercontent.com/ocornut/imgui/master/LICENSE.txt",
|
||||
ships_static=all_platforms,
|
||||
submodule=Submodule("subprojects/imgui.wrap"),
|
||||
),
|
||||
Lib(
|
||||
"implot",
|
||||
"https://github.com/epezent/implot",
|
||||
mit,
|
||||
"https://raw.githubusercontent.com/epezent/implot/master/LICENSE",
|
||||
ships_static=all_platforms,
|
||||
submodule=Submodule("subprojects/implot.wrap"),
|
||||
),
|
||||
Lib(
|
||||
"noc",
|
||||
"https://github.com/guillaumechereau/noc/blob/master/noc_file_dialog.h",
|
||||
mit,
|
||||
"https://raw.githubusercontent.com/xemu-project/xemu/master/ui/noc_file_dialog.h",
|
||||
license_lines=(1, 22),
|
||||
ships_static=all_platforms,
|
||||
version="78b2e7b22506429dd1755ffff197c7da11507fd9",
|
||||
),
|
||||
Lib(
|
||||
"stb_image",
|
||||
"https://github.com/nothings/stb",
|
||||
mit,
|
||||
"https://raw.githubusercontent.com/nothings/stb/master/LICENSE",
|
||||
license_lines=(4, 19),
|
||||
ships_static=all_platforms,
|
||||
version="2.25",
|
||||
),
|
||||
Lib(
|
||||
"tomlplusplus",
|
||||
"https://github.com/marzer/tomlplusplus",
|
||||
mit,
|
||||
"https://raw.githubusercontent.com/marzer/tomlplusplus/master/LICENSE",
|
||||
ships_static=all_platforms,
|
||||
submodule=Submodule("subprojects/tomlplusplus.wrap"),
|
||||
),
|
||||
Lib(
|
||||
"xxHash",
|
||||
"https://github.com/Cyan4973/xxHash.git",
|
||||
bsd,
|
||||
"https://raw.githubusercontent.com/Cyan4973/xxHash/dev/LICENSE",
|
||||
license_lines=(1, 26),
|
||||
ships_static=all_platforms,
|
||||
submodule=Submodule("subprojects/xxhash.wrap"),
|
||||
),
|
||||
Lib(
|
||||
"fpng",
|
||||
"https://github.com/richgel999/fpng",
|
||||
unlicense,
|
||||
"https://github.com/richgel999/fpng/blob/main/README.md",
|
||||
ships_static=all_platforms,
|
||||
version="6926f5a0a78f22d42b074a0ab8032e07736babd4",
|
||||
),
|
||||
Lib(
|
||||
"nv2a_vsh_cpu",
|
||||
"https://github.com/xemu-project/nv2a_vsh_cpu",
|
||||
unlicense,
|
||||
"https://raw.githubusercontent.com/xemu-project/nv2a_vsh_cpu/main/LICENSE",
|
||||
ships_static=all_platforms,
|
||||
submodule=Submodule("subprojects/nv2a_vsh_cpu.wrap"),
|
||||
),
|
||||
Lib(
|
||||
"volk",
|
||||
"https://github.com/zeux/volk",
|
||||
mit,
|
||||
"https://raw.githubusercontent.com/zeux/volk/master/LICENSE.md",
|
||||
ships_static=all_platforms,
|
||||
submodule=Submodule("subprojects/volk.wrap"),
|
||||
),
|
||||
Lib(
|
||||
"VulkanMemoryAllocator",
|
||||
"https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator",
|
||||
mit,
|
||||
"https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator/master/LICENSE.txt",
|
||||
ships_static=all_platforms,
|
||||
submodule=Submodule("subprojects/VulkanMemoryAllocator.wrap"),
|
||||
),
|
||||
Lib(
|
||||
"SPIRV-Reflect",
|
||||
"https://github.com/KhronosGroup/SPIRV-Reflect",
|
||||
apache2,
|
||||
"https://raw.githubusercontent.com/KhronosGroup/SPIRV-Reflect/main/LICENSE",
|
||||
ships_static=all_platforms,
|
||||
submodule=Submodule("subprojects/SPIRV-Reflect.wrap"),
|
||||
),
|
||||
Lib(
|
||||
"glslang",
|
||||
"https://github.com/KhronosGroup/glslang",
|
||||
bsd_3clause,
|
||||
"https://raw.githubusercontent.com/KhronosGroup/glslang/main/LICENSE.txt",
|
||||
ships_static=all_platforms,
|
||||
submodule=Submodule("subprojects/glslang.wrap"),
|
||||
),
|
||||
Lib(
|
||||
"NVIDIA NVAPI",
|
||||
"https://github.com/NVIDIA/nvapi",
|
||||
mit,
|
||||
license_path="thirdparty/nvapi/nvapi_defs.LICENSE.txt",
|
||||
version="R575",
|
||||
ships_static={windows},
|
||||
),
|
||||
#
|
||||
# Data files included with xemu
|
||||
#
|
||||
Lib(
|
||||
"roboto",
|
||||
"https://github.com/googlefonts/roboto",
|
||||
apache2,
|
||||
"https://raw.githubusercontent.com/googlefonts/roboto/main/LICENSE",
|
||||
ships_static=all_platforms,
|
||||
version="2.138",
|
||||
),
|
||||
Lib(
|
||||
"fontawesome",
|
||||
"https://fontawesome.com",
|
||||
multi,
|
||||
"",
|
||||
ships_static=all_platforms,
|
||||
version="6.1.1",
|
||||
),
|
||||
#
|
||||
# Libraries either linked statically, dynamically linked & shipped, or dynamically linked with system-installed libraries only
|
||||
#
|
||||
Lib(
|
||||
"sdl2",
|
||||
"https://www.libsdl.org/",
|
||||
zlib,
|
||||
"https://raw.githubusercontent.com/libsdl-org/SDL/main/LICENSE.txt",
|
||||
ships_static={windows},
|
||||
ships_dynamic={macos},
|
||||
pkgconfig=PkgConfig("sdl2"),
|
||||
pkg_win="sdl2",
|
||||
pkg_mac="sdl2",
|
||||
pkg_ubuntu="libsdl2-dev",
|
||||
),
|
||||
Lib(
|
||||
"glib-2.0",
|
||||
"https://gitlab.gnome.org/GNOME/glib",
|
||||
lgplv2_1,
|
||||
"https://gitlab.gnome.org/GNOME/glib/-/raw/master/COPYING",
|
||||
ships_static={windows},
|
||||
ships_dynamic={macos},
|
||||
pkgconfig=PkgConfig("glib-2.0"),
|
||||
pkg_win="glib",
|
||||
pkg_mac="glib",
|
||||
pkg_ubuntu="libglib2.0-dev",
|
||||
),
|
||||
# glib dep
|
||||
Lib(
|
||||
"pcre",
|
||||
"http://pcre.org/",
|
||||
bsd,
|
||||
"http://www.pcre.org/original/license.txt",
|
||||
pkgconfig=PkgConfig("libpcre"),
|
||||
pkg_ubuntu="libpcre3-dev",
|
||||
),
|
||||
Lib(
|
||||
"pcre2",
|
||||
"http://pcre.org/",
|
||||
bsd,
|
||||
"https://www.pcre.org/licence.txt",
|
||||
ships_static={windows},
|
||||
ships_dynamic={macos},
|
||||
pkgconfig=PkgConfig("libpcre2-8"),
|
||||
pkg_win="pcre2",
|
||||
pkg_mac="pcre2",
|
||||
pkg_ubuntu="libpcre2-dev",
|
||||
),
|
||||
# glib dep
|
||||
Lib(
|
||||
"gettext",
|
||||
"https://www.gnu.org/software/gettext/",
|
||||
lgplv2_1,
|
||||
"https://git.savannah.gnu.org/gitweb/?p=gettext.git;a=blob_plain;f=gettext-runtime/intl/COPYING.LIB;hb=HEAD",
|
||||
ships_static={windows},
|
||||
ships_dynamic={macos},
|
||||
pkg_win="gettext",
|
||||
pkg_mac="gettext-runtime",
|
||||
),
|
||||
# glib dep
|
||||
Lib(
|
||||
"iconv",
|
||||
"https://www.gnu.org/software/libiconv/",
|
||||
lgplv2_1,
|
||||
"https://git.savannah.gnu.org/gitweb/?p=libiconv.git;a=blob_plain;f=COPYING.LIB;hb=HEAD",
|
||||
ships_static={windows},
|
||||
ships_dynamic={macos},
|
||||
pkg_win="libiconv",
|
||||
pkg_mac="libiconv",
|
||||
),
|
||||
Lib(
|
||||
"libepoxy",
|
||||
"https://github.com/anholt/libepoxy",
|
||||
mit,
|
||||
"https://raw.githubusercontent.com/anholt/libepoxy/master/COPYING",
|
||||
ships_static={windows},
|
||||
ships_dynamic={macos},
|
||||
pkgconfig=PkgConfig("epoxy"),
|
||||
pkg_win="libepoxy",
|
||||
pkg_mac="libepoxy",
|
||||
pkg_ubuntu="libepoxy-dev",
|
||||
),
|
||||
Lib(
|
||||
"pixman",
|
||||
"http://www.pixman.org/",
|
||||
mit,
|
||||
"https://cgit.freedesktop.org/pixman/plain/COPYING",
|
||||
ships_static={windows},
|
||||
ships_dynamic={macos},
|
||||
pkgconfig=PkgConfig("pixman-1"),
|
||||
pkg_win="pixman",
|
||||
pkg_mac="pixman",
|
||||
pkg_ubuntu="libpixman-1-dev",
|
||||
),
|
||||
Lib(
|
||||
"libsamplerate",
|
||||
"https://github.com/libsndfile/libsamplerate",
|
||||
bsd_2clause,
|
||||
"https://raw.githubusercontent.com/libsndfile/libsamplerate/master/COPYING",
|
||||
ships_static={windows},
|
||||
ships_dynamic={macos},
|
||||
pkgconfig=PkgConfig("samplerate"),
|
||||
pkg_win="libsamplerate",
|
||||
pkg_mac="libsamplerate",
|
||||
),
|
||||
Lib(
|
||||
"zlib",
|
||||
"https://zlib.net/",
|
||||
zlib,
|
||||
"https://raw.githubusercontent.com/madler/zlib/master/README",
|
||||
license_lines=(87, 106),
|
||||
ships_static={windows},
|
||||
ships_dynamic={macos},
|
||||
pkgconfig=PkgConfig("zlib"),
|
||||
pkg_win="zlib",
|
||||
pkg_mac="zlib",
|
||||
pkg_ubuntu="zlib1g-dev",
|
||||
),
|
||||
Lib(
|
||||
"libmingw32",
|
||||
"http://mingw-w64.org/",
|
||||
multi,
|
||||
"https://sourceforge.net/p/mingw-w64/mingw-w64/ci/master/tree/COPYING.MinGW-w64-runtime/COPYING.MinGW-w64-runtime.txt?format=raw",
|
||||
ships_static={windows},
|
||||
platform={windows},
|
||||
pkg_win="mingw-w64",
|
||||
),
|
||||
Lib(
|
||||
"gtk",
|
||||
"https://www.gtk.org/",
|
||||
lgplv2_1,
|
||||
"https://gitlab.gnome.org/GNOME/gtk/-/raw/master/COPYING",
|
||||
platform={linux},
|
||||
pkgconfig=PkgConfig("gtk+-3.0"),
|
||||
pkg_ubuntu="libgtk-3-dev",
|
||||
),
|
||||
Lib(
|
||||
"miniz",
|
||||
"https://github.com/richgel999/miniz",
|
||||
lgplv2_1,
|
||||
"https://raw.githubusercontent.com/richgel999/miniz/master/LICENSE",
|
||||
ships_static={windows},
|
||||
platform={windows},
|
||||
version="2.1.0",
|
||||
),
|
||||
Lib(
|
||||
"libcurl",
|
||||
"https://curl.se/",
|
||||
mit,
|
||||
"https://raw.githubusercontent.com/curl/curl/refs/heads/master/COPYING",
|
||||
ships_static={windows},
|
||||
platform={windows},
|
||||
submodule=Submodule("subprojects/curl.wrap"),
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
def gen_license():
|
||||
print(f'''\
|
||||
print(
|
||||
f"""\
|
||||
xemu is free and open source software. This binary of xemu has been made
|
||||
available to you under the terms of the GNU General Public License, version 2.
|
||||
|
||||
|
@ -390,36 +540,42 @@ The source code used to build this version of xemu is available at:
|
|||
|
||||
xemu depends on several great packages/libraries which are also free and open
|
||||
source. The respective licenses of these packages are provided below.
|
||||
''')
|
||||
for lib in LIBS:
|
||||
if lib.does_ship:
|
||||
print(banner(lib.name))
|
||||
print('')
|
||||
print('Project URL: ' + lib.url)
|
||||
print('Version Included: ' + lib.version)
|
||||
print('Project License:')
|
||||
"""
|
||||
)
|
||||
for lib in LIBS:
|
||||
if lib.does_ship:
|
||||
print(banner(lib.name))
|
||||
print("")
|
||||
print("Project URL: " + lib.url)
|
||||
print("Version Included: " + lib.version)
|
||||
print("Project License:")
|
||||
|
||||
print("")
|
||||
print("\n".join([(" | " + l) for l in lib.license_text.splitlines()]))
|
||||
print("")
|
||||
|
||||
print('')
|
||||
print('\n'.join([(' | ' + l) for l in lib.license_text.splitlines()]))
|
||||
print('')
|
||||
|
||||
def main():
|
||||
import argparse
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument('--platform', default='')
|
||||
ap.add_argument('--version-file', default='')
|
||||
args = ap.parse_args()
|
||||
import argparse
|
||||
|
||||
if args.platform == '':
|
||||
args.platform = sys.platform.lower()
|
||||
global current_platform
|
||||
current_platform = args.platform
|
||||
if args.version_file != '':
|
||||
with open(args.version_file, 'r') as f:
|
||||
global versions
|
||||
versions = {pkg: ver
|
||||
for pkg, ver in map(lambda l: l.strip().split('='), f.readlines())}
|
||||
gen_license()
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("--platform", default="")
|
||||
ap.add_argument("--version-file", default="")
|
||||
args = ap.parse_args()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
if args.platform == "":
|
||||
args.platform = sys.platform.lower()
|
||||
global current_platform
|
||||
current_platform = args.platform
|
||||
if args.version_file != "":
|
||||
with open(args.version_file, "r") as f:
|
||||
global versions
|
||||
versions = {
|
||||
pkg: ver
|
||||
for pkg, ver in map(lambda l: l.strip().split("="), f.readlines())
|
||||
}
|
||||
gen_license()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[wrap-git]
|
||||
url = https://github.com/KhronosGroup/SPIRV-Reflect
|
||||
revision = c6c0f5c9796bdef40c55065d82e0df67c38a29a4
|
||||
revision = e55086b044225f9b511ae44dbf9b079d3625943f
|
||||
depth = 1
|
||||
|
||||
[update]
|
||||
|
|
|
@ -26,3 +26,5 @@ vma = declare_dependency(include_directories: vma_subproj.include_directories('V
|
|||
dependencies: vulkan)
|
||||
|
||||
endif
|
||||
|
||||
subdir('nvapi')
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
if host_os == 'windows'
|
||||
libnvapi = static_library('nvapi', files(['nvapi.c']))
|
||||
nvapi = declare_dependency(link_with: libnvapi, include_directories: ['.'])
|
||||
endif
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* NVIDIA Driver Settings Management
|
||||
*
|
||||
* Copyright (c) 2025 Matt Borgerson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <windows.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include "nvapi.h"
|
||||
#include "nvapi_defs.h"
|
||||
|
||||
#define LOG(fmt, ...) fprintf(stderr, "nvapi: " fmt "\n", ##__VA_ARGS__)
|
||||
|
||||
static HMODULE g_hnvapi;
|
||||
static NvAPI_QueryInterface_t NvAPI_QueryInterface;
|
||||
#define DECL_NVAPI_FUNC(name, id) static name##_t name;
|
||||
NVAPI_FUNCS_X(DECL_NVAPI_FUNC)
|
||||
|
||||
static bool init_nvapi_func(const char *name, unsigned int interface_id,
|
||||
void **ptr)
|
||||
{
|
||||
*ptr = NvAPI_QueryInterface(interface_id);
|
||||
if (*ptr == NULL) {
|
||||
LOG("Failed to resolve %s", name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nvapi_init(void)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
g_hnvapi = LoadLibraryA("nvapi64.dll");
|
||||
#else
|
||||
g_hnvapi = LoadLibraryA("nvapi.dll");
|
||||
#endif
|
||||
if (g_hnvapi == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NvAPI_QueryInterface = (NvAPI_QueryInterface_t)GetProcAddress(
|
||||
g_hnvapi, "nvapi_QueryInterface");
|
||||
if (NvAPI_QueryInterface == NULL) {
|
||||
LOG("GetProcAddress failed for NvAPI_QueryInterface");
|
||||
goto error;
|
||||
}
|
||||
|
||||
#define INIT_NVAPI_FUNC(name, id) \
|
||||
if (!init_nvapi_func(#name, id, (void *)&name)) \
|
||||
goto error;
|
||||
NVAPI_FUNCS_X(INIT_NVAPI_FUNC)
|
||||
|
||||
if (NvAPI_Initialize()) {
|
||||
LOG("NvAPI_Initialize failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
FreeLibrary(g_hnvapi);
|
||||
g_hnvapi = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
void nvapi_finalize(void)
|
||||
{
|
||||
if (g_hnvapi) {
|
||||
NvAPI_Unload();
|
||||
g_hnvapi = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool nvapi_setup_profile(NvApiProfileOpts opts)
|
||||
{
|
||||
if (g_hnvapi == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
NvDRSSessionHandle session;
|
||||
if (NvAPI_DRS_CreateSession(&session)) {
|
||||
LOG("NvAPI_DRS_CreateSession failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NvAPI_DRS_LoadSettings(session)) {
|
||||
LOG("NvAPI_DRS_LoadSettings failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
NvDRSProfileHandle profile = NULL;
|
||||
if (NvAPI_DRS_FindProfileByName(session, (NvU16 *)opts.profile_name,
|
||||
&profile)) {
|
||||
NVDRS_PROFILE profile_info = {
|
||||
.version = NVDRS_PROFILE_VER,
|
||||
.isPredefined = 0,
|
||||
};
|
||||
wcsncpy(profile_info.profileName, opts.profile_name,
|
||||
sizeof(profile_info.profileName) / sizeof(wchar_t));
|
||||
if (NvAPI_DRS_CreateProfile(session, &profile_info, &profile)) {
|
||||
LOG("NvAPI_DRS_CreateProfile failed");
|
||||
goto cleanup;
|
||||
}
|
||||
LOG("Created new profile");
|
||||
}
|
||||
|
||||
NVDRS_APPLICATION_V4 app = { .version = NVDRS_APPLICATION_VER_V4 };
|
||||
if (NvAPI_DRS_GetApplicationInfo(session, profile,
|
||||
(NvU16 *)opts.executable_name, &app)) {
|
||||
app.isPredefined = 0;
|
||||
app.launcher[0] = 0;
|
||||
app.fileInFolder[0] = 0;
|
||||
wcsncpy(app.appName, opts.executable_name,
|
||||
sizeof(app.appName) / sizeof(wchar_t));
|
||||
if (NvAPI_DRS_CreateApplication(session, profile, &app)) {
|
||||
LOG("NvAPI_DRS_CreateApplication failed");
|
||||
goto cleanup;
|
||||
}
|
||||
LOG("Added application to profile");
|
||||
}
|
||||
|
||||
NVDRS_SETTING setting = {
|
||||
.version = NVDRS_SETTING_VER,
|
||||
.settingId = OGL_THREAD_CONTROL_ID,
|
||||
.settingType = NVDRS_DWORD_TYPE,
|
||||
.u32CurrentValue = opts.threaded_optimization ?
|
||||
OGL_THREAD_CONTROL_ENABLE :
|
||||
OGL_THREAD_CONTROL_DISABLE,
|
||||
};
|
||||
if (NvAPI_DRS_SetSetting(session, profile, &setting)) {
|
||||
LOG("NvAPI_DRS_SetSetting for settingId %x failed",
|
||||
setting.settingId);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (NvAPI_DRS_SaveSettings(session)) {
|
||||
LOG("NvAPI_DRS_SaveSettings failed");
|
||||
goto cleanup;
|
||||
}
|
||||
LOG("Saved settings");
|
||||
result = true;
|
||||
|
||||
cleanup:
|
||||
NvAPI_DRS_DestroySession(session);
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* NVIDIA Driver Settings Management
|
||||
*
|
||||
* Copyright (c) 2025 Matt Borgerson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef NVAPI_H
|
||||
#define NVAPI_H
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct NvApiProfileOpts {
|
||||
const wchar_t *profile_name;
|
||||
const wchar_t *executable_name;
|
||||
bool threaded_optimization;
|
||||
} NvApiProfileOpts;
|
||||
|
||||
bool nvapi_init(void);
|
||||
bool nvapi_setup_profile(NvApiProfileOpts opts);
|
||||
void nvapi_finalize(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,22 @@
|
|||
Headers from the NVIDIA NVAPI SDK:
|
||||
|
||||
SPDX-FileCopyrightText: Copyright (c) 2019-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
SPDX-License-Identifier: MIT
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,242 @@
|
|||
/*
|
||||
* Definitions for interacting with the NVAPI library from the NVIDIA NVAPI
|
||||
* SDK:
|
||||
*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2019-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef NVAPI_DEFS_H
|
||||
#define NVAPI_DEFS_H
|
||||
|
||||
// clang-format off
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum ESetting {
|
||||
OGL_THREAD_CONTROL_ID = 0x20C1221E,
|
||||
};
|
||||
|
||||
enum EValues_OGL_THREAD_CONTROL {
|
||||
OGL_THREAD_CONTROL_ENABLE = 0x00000001,
|
||||
OGL_THREAD_CONTROL_DISABLE = 0x00000002,
|
||||
OGL_THREAD_CONTROL_NUM_VALUES = 2,
|
||||
OGL_THREAD_CONTROL_DEFAULT = 0U
|
||||
};
|
||||
|
||||
typedef uint32_t NvU32;
|
||||
typedef uint16_t NvU16;
|
||||
typedef uint8_t NvU8;
|
||||
|
||||
#define MAKE_NVAPI_VERSION(typeName,ver) (NvU32)(sizeof(typeName) | ((ver)<<16))
|
||||
|
||||
#define NV_DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name
|
||||
|
||||
NV_DECLARE_HANDLE(NvDRSSessionHandle);
|
||||
NV_DECLARE_HANDLE(NvDRSProfileHandle);
|
||||
|
||||
#define NVAPI_UNICODE_STRING_MAX 2048
|
||||
#define NVAPI_BINARY_DATA_MAX 4096
|
||||
typedef NvU16 NvAPI_UnicodeString[NVAPI_UNICODE_STRING_MAX];
|
||||
typedef char NvAPI_ShortString[64];
|
||||
|
||||
#define NVAPI_SETTING_MAX_VALUES 100
|
||||
|
||||
typedef enum _NVDRS_SETTING_TYPE
|
||||
{
|
||||
NVDRS_DWORD_TYPE,
|
||||
NVDRS_BINARY_TYPE,
|
||||
NVDRS_STRING_TYPE,
|
||||
NVDRS_WSTRING_TYPE
|
||||
} NVDRS_SETTING_TYPE;
|
||||
|
||||
typedef enum _NVDRS_SETTING_LOCATION
|
||||
{
|
||||
NVDRS_CURRENT_PROFILE_LOCATION,
|
||||
NVDRS_GLOBAL_PROFILE_LOCATION,
|
||||
NVDRS_BASE_PROFILE_LOCATION,
|
||||
NVDRS_DEFAULT_PROFILE_LOCATION
|
||||
} NVDRS_SETTING_LOCATION;
|
||||
|
||||
typedef struct _NVDRS_GPU_SUPPORT
|
||||
{
|
||||
NvU32 geforce : 1;
|
||||
NvU32 quadro : 1;
|
||||
NvU32 nvs : 1;
|
||||
NvU32 reserved4 : 1;
|
||||
NvU32 reserved5 : 1;
|
||||
NvU32 reserved6 : 1;
|
||||
NvU32 reserved7 : 1;
|
||||
NvU32 reserved8 : 1;
|
||||
NvU32 reserved9 : 1;
|
||||
NvU32 reserved10 : 1;
|
||||
NvU32 reserved11 : 1;
|
||||
NvU32 reserved12 : 1;
|
||||
NvU32 reserved13 : 1;
|
||||
NvU32 reserved14 : 1;
|
||||
NvU32 reserved15 : 1;
|
||||
NvU32 reserved16 : 1;
|
||||
NvU32 reserved17 : 1;
|
||||
NvU32 reserved18 : 1;
|
||||
NvU32 reserved19 : 1;
|
||||
NvU32 reserved20 : 1;
|
||||
NvU32 reserved21 : 1;
|
||||
NvU32 reserved22 : 1;
|
||||
NvU32 reserved23 : 1;
|
||||
NvU32 reserved24 : 1;
|
||||
NvU32 reserved25 : 1;
|
||||
NvU32 reserved26 : 1;
|
||||
NvU32 reserved27 : 1;
|
||||
NvU32 reserved28 : 1;
|
||||
NvU32 reserved29 : 1;
|
||||
NvU32 reserved30 : 1;
|
||||
NvU32 reserved31 : 1;
|
||||
NvU32 reserved32 : 1;
|
||||
} NVDRS_GPU_SUPPORT;
|
||||
|
||||
//! Enum to decide on the datatype of setting value.
|
||||
typedef struct _NVDRS_BINARY_SETTING
|
||||
{
|
||||
NvU32 valueLength; //!< valueLength should always be in number of bytes.
|
||||
NvU8 valueData[NVAPI_BINARY_DATA_MAX];
|
||||
} NVDRS_BINARY_SETTING;
|
||||
|
||||
typedef struct _NVDRS_SETTING_VALUES
|
||||
{
|
||||
NvU32 version; //!< Structure Version
|
||||
NvU32 numSettingValues; //!< Total number of values available in a setting.
|
||||
NVDRS_SETTING_TYPE settingType; //!< Type of setting value.
|
||||
union //!< Setting can hold either DWORD or Binary value or string. Not mixed types.
|
||||
{
|
||||
NvU32 u32DefaultValue; //!< Accessing default DWORD value of this setting.
|
||||
NVDRS_BINARY_SETTING binaryDefaultValue; //!< Accessing default Binary value of this setting.
|
||||
//!< Must be allocated by caller with valueLength specifying buffer size, or only valueLength will be filled in.
|
||||
NvAPI_UnicodeString wszDefaultValue; //!< Accessing default unicode string value of this setting.
|
||||
};
|
||||
union //!< Setting values can be of either DWORD, Binary values or String type,
|
||||
{ //!< NOT mixed types.
|
||||
NvU32 u32Value; //!< All possible DWORD values for a setting
|
||||
NVDRS_BINARY_SETTING binaryValue; //!< All possible Binary values for a setting
|
||||
NvAPI_UnicodeString wszValue; //!< Accessing current unicode string value of this setting.
|
||||
}settingValues[NVAPI_SETTING_MAX_VALUES];
|
||||
} NVDRS_SETTING_VALUES;
|
||||
|
||||
//! Macro for constructing the version field of ::_NVDRS_SETTING_VALUES
|
||||
#define NVDRS_SETTING_VALUES_VER MAKE_NVAPI_VERSION(NVDRS_SETTING_VALUES,1)
|
||||
|
||||
typedef struct _NVDRS_SETTING_V1
|
||||
{
|
||||
NvU32 version; //!< Structure Version
|
||||
NvAPI_UnicodeString settingName; //!< String name of setting
|
||||
NvU32 settingId; //!< 32 bit setting Id
|
||||
NVDRS_SETTING_TYPE settingType; //!< Type of setting value.
|
||||
NVDRS_SETTING_LOCATION settingLocation; //!< Describes where the value in CurrentValue comes from.
|
||||
NvU32 isCurrentPredefined; //!< It is different than 0 if the currentValue is a predefined Value,
|
||||
//!< 0 if the currentValue is a user value.
|
||||
NvU32 isPredefinedValid; //!< It is different than 0 if the PredefinedValue union contains a valid value.
|
||||
union //!< Setting can hold either DWORD or Binary value or string. Not mixed types.
|
||||
{
|
||||
NvU32 u32PredefinedValue; //!< Accessing default DWORD value of this setting.
|
||||
NVDRS_BINARY_SETTING binaryPredefinedValue; //!< Accessing default Binary value of this setting.
|
||||
//!< Must be allocated by caller with valueLength specifying buffer size,
|
||||
//!< or only valueLength will be filled in.
|
||||
NvAPI_UnicodeString wszPredefinedValue; //!< Accessing default unicode string value of this setting.
|
||||
};
|
||||
union //!< Setting can hold either DWORD or Binary value or string. Not mixed types.
|
||||
{
|
||||
NvU32 u32CurrentValue; //!< Accessing current DWORD value of this setting.
|
||||
NVDRS_BINARY_SETTING binaryCurrentValue; //!< Accessing current Binary value of this setting.
|
||||
//!< Must be allocated by caller with valueLength specifying buffer size,
|
||||
//!< or only valueLength will be filled in.
|
||||
NvAPI_UnicodeString wszCurrentValue; //!< Accessing current unicode string value of this setting.
|
||||
};
|
||||
} NVDRS_SETTING_V1;
|
||||
|
||||
//! Macro for constructing the version field of ::_NVDRS_SETTING
|
||||
#define NVDRS_SETTING_VER1 MAKE_NVAPI_VERSION(NVDRS_SETTING_V1, 1)
|
||||
|
||||
typedef NVDRS_SETTING_V1 NVDRS_SETTING;
|
||||
#define NVDRS_SETTING_VER NVDRS_SETTING_VER1
|
||||
|
||||
typedef struct _NVDRS_APPLICATION_V4
|
||||
{
|
||||
NvU32 version; //!< Structure Version
|
||||
NvU32 isPredefined; //!< Is the application userdefined/predefined
|
||||
NvAPI_UnicodeString appName; //!< String name of the Application
|
||||
NvAPI_UnicodeString userFriendlyName; //!< UserFriendly name of the Application
|
||||
NvAPI_UnicodeString launcher; //!< Indicates the name (if any) of the launcher that starts the Application
|
||||
NvAPI_UnicodeString fileInFolder; //!< Select this application only if this file is found.
|
||||
//!< When specifying multiple files, separate them using the ':' character.
|
||||
NvU32 isMetro:1; //!< Windows 8 style app
|
||||
NvU32 isCommandLine:1; //!< Command line parsing for the application name
|
||||
NvU32 reserved:30; //!< Reserved. Should be 0.
|
||||
NvAPI_UnicodeString commandLine; //!< If isCommandLine is set to 0 this must be an empty. If isCommandLine is set to 1
|
||||
//!< this contains application's command line as if it was returned by GetCommandLineW.
|
||||
} NVDRS_APPLICATION_V4;
|
||||
|
||||
#define NVDRS_APPLICATION_VER_V4 MAKE_NVAPI_VERSION(NVDRS_APPLICATION_V4,4)
|
||||
|
||||
typedef NVDRS_APPLICATION_V4 NVDRS_APPLICATION;
|
||||
#define NVDRS_APPLICATION_VER NVDRS_APPLICATION_VER_V4
|
||||
|
||||
typedef struct _NVDRS_PROFILE_V1
|
||||
{
|
||||
NvU32 version; //!< Structure Version
|
||||
NvAPI_UnicodeString profileName; //!< String name of the Profile
|
||||
NVDRS_GPU_SUPPORT gpuSupport; //!< This read-only flag indicates the profile support on either
|
||||
//!< Quadro, or Geforce, or both.
|
||||
NvU32 isPredefined; //!< Is the Profile user-defined, or predefined
|
||||
NvU32 numOfApps; //!< Total number of applications that belong to this profile. Read-only
|
||||
NvU32 numOfSettings; //!< Total number of settings applied for this Profile. Read-only
|
||||
} NVDRS_PROFILE_V1;
|
||||
|
||||
typedef NVDRS_PROFILE_V1 NVDRS_PROFILE;
|
||||
|
||||
//! Macro for constructing the version field of ::NVDRS_PROFILE
|
||||
#define NVDRS_PROFILE_VER1 MAKE_NVAPI_VERSION(NVDRS_PROFILE_V1,1)
|
||||
#define NVDRS_PROFILE_VER NVDRS_PROFILE_VER1
|
||||
|
||||
#define NVAPI_FUNCS_X(FUNC) \
|
||||
FUNC(NvAPI_DRS_CreateApplication, 0x4347A9DE) \
|
||||
FUNC(NvAPI_DRS_CreateProfile, 0xCC176068) \
|
||||
FUNC(NvAPI_DRS_CreateSession, 0x0694D52E) \
|
||||
FUNC(NvAPI_DRS_DestroySession, 0xDAD9CFF8) \
|
||||
FUNC(NvAPI_DRS_FindProfileByName, 0x7E4A9A0B) \
|
||||
FUNC(NvAPI_DRS_GetApplicationInfo, 0xED1F8C69) \
|
||||
FUNC(NvAPI_DRS_LoadSettings, 0x375DBD6B) \
|
||||
FUNC(NvAPI_DRS_SaveSettings, 0xFCBC7E14) \
|
||||
FUNC(NvAPI_DRS_SetSetting, 0x577DD202) \
|
||||
FUNC(NvAPI_Initialize, 0x0150E828) \
|
||||
FUNC(NvAPI_Unload, 0xD22BDD7E)
|
||||
|
||||
typedef int(__cdecl *NvAPI_DRS_CreateApplication_t)(NvDRSSessionHandle, NvDRSProfileHandle, NVDRS_APPLICATION *);
|
||||
typedef int(__cdecl *NvAPI_DRS_CreateProfile_t)(NvDRSSessionHandle, NVDRS_PROFILE *, NvDRSProfileHandle *);
|
||||
typedef int(__cdecl *NvAPI_DRS_CreateSession_t)(NvDRSSessionHandle *);
|
||||
typedef int(__cdecl *NvAPI_DRS_DestroySession_t)(NvDRSSessionHandle);
|
||||
typedef int(__cdecl *NvAPI_DRS_FindProfileByName_t)(NvDRSSessionHandle, NvAPI_UnicodeString, NvDRSProfileHandle *);
|
||||
typedef int(__cdecl *NvAPI_DRS_GetApplicationInfo_t)(NvDRSSessionHandle, NvDRSProfileHandle, NvAPI_UnicodeString, NVDRS_APPLICATION *);
|
||||
typedef int(__cdecl *NvAPI_DRS_LoadSettings_t)(NvDRSSessionHandle);
|
||||
typedef int(__cdecl *NvAPI_DRS_SaveSettings_t)(NvDRSSessionHandle);
|
||||
typedef int(__cdecl *NvAPI_DRS_SetSetting_t)(NvDRSSessionHandle, NvDRSProfileHandle, NVDRS_SETTING *);
|
||||
typedef int(__cdecl *NvAPI_Initialize_t)(void);
|
||||
typedef int(__cdecl *NvAPI_Unload_t)(void);
|
||||
typedef void *(__cdecl *NvAPI_QueryInterface_t)(unsigned int interface_id);
|
||||
|
||||
#endif
|
|
@ -36,6 +36,10 @@ xemu_ss.add(files(
|
|||
'xemu-widescreen.c',
|
||||
))
|
||||
|
||||
if host_os == 'windows'
|
||||
xemu_ss.add(nvapi)
|
||||
endif
|
||||
|
||||
subdir('xui')
|
||||
|
||||
if host_os == 'darwin'
|
||||
|
|
52
ui/xemu.c
52
ui/xemu.c
|
@ -61,6 +61,7 @@
|
|||
#include <locale.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "nvapi.h"
|
||||
// Provide hint to prefer high-performance graphics for hybrid systems
|
||||
// https://gpuopen.com/learn/amdpowerxpressrequesthighperformance/
|
||||
__declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 1;
|
||||
|
@ -1266,6 +1267,51 @@ static void sleep_ns(int64_t ns)
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static const wchar_t *get_executable_name(void)
|
||||
{
|
||||
static wchar_t exe_name[MAX_PATH] = { 0 };
|
||||
static bool initialized = false;
|
||||
|
||||
if (!initialized) {
|
||||
wchar_t full_path[MAX_PATH];
|
||||
DWORD length = GetModuleFileNameW(NULL, full_path, MAX_PATH);
|
||||
if (length == 0 || length == MAX_PATH) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wchar_t *last_slash = wcsrchr(full_path, L'\\');
|
||||
if (last_slash) {
|
||||
wcsncpy_s(exe_name, MAX_PATH, last_slash + 1, _TRUNCATE);
|
||||
} else {
|
||||
wcsncpy_s(exe_name, MAX_PATH, full_path, _TRUNCATE);
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
return exe_name;
|
||||
}
|
||||
|
||||
static void setup_nvidia_profile(void)
|
||||
{
|
||||
const wchar_t *exe_name = get_executable_name();
|
||||
if (exe_name == NULL) {
|
||||
fprintf(stderr, "Failed to get current executable name\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (nvapi_init()) {
|
||||
nvapi_setup_profile((NvApiProfileOpts){
|
||||
.profile_name = L"xemu",
|
||||
.executable_name = exe_name,
|
||||
.threaded_optimization = false,
|
||||
});
|
||||
nvapi_finalize();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QemuThread thread;
|
||||
|
@ -1325,6 +1371,12 @@ int main(int argc, char **argv)
|
|||
}
|
||||
atexit(xemu_settings_save);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (g_config.display.setup_nvidia_profile) {
|
||||
setup_nvidia_profile();
|
||||
}
|
||||
#endif
|
||||
|
||||
sdl2_display_very_early_init(NULL);
|
||||
|
||||
qemu_sem_init(&display_init_sem, 0);
|
||||
|
|
Loading…
Reference in New Issue