Compare commits

..

No commits in common. "main" and "v1.0.6" have entirely different histories.
main ... v1.0.6

7 changed files with 24 additions and 196 deletions

View File

@ -1 +1 @@
1
2

145
README.md
View File

@ -1,145 +0,0 @@
# falcond - Advanced Linux Gaming Performance Daemon
falcond is a powerful system daemon designed to automatically optimize your Linux gaming experience. It intelligently manages system resources and performance settings on a per-game basis, eliminating the need to manually configure settings for each game.
## Features
- **Automatic Game Detection**: Automatically detects running games and applies optimized settings
- **Per-Game Profiles**: Customizable profiles for different games
- **Performance Mode**: Enables system-wide performance optimizations when gaming
- **3D vcache Management**: Smart management of AMD 3D vcache settings
- **SCX Scheduler Integration**: Dynamically pick a scheduler that is best for the specific game
- **Proton Compatibility**: Full support for Steam Proton games, with a global profile for excellent game coverage
- **Low Overhead**: Minimal system resource usage
- **Different Device Modes**: Profiles for desktops, handhelds, HTPC etc
## Installation
falcond is available on PikaOS via the falcond package or via the Pika Gameutils Metapackage. For other distributions, please check your package manager or build from source.
## Configuration
The configuration file is located at `/etc/falcond/config.conf`. Here's an example configuration, it will be generated automatically on first run:
```
enable_performance_mode = true
scx_sched = none
scx_sched_props = default
vcache_mode = none
profile_mode = none
```
This is global configuration and all options other than profile_mode override individual game profiles.
There is also a list of proton/wine system processes in `/usr/share/falcond/system.conf`. This list can be updated if for example a crash handler is intercepting your profile and needs to be ignored.
### Configuration Options
- `enable_performance_mode`: Enable/disable performance mode (default: true)
- `scx_sched`: SCX scheduler (options: none, bpfland, lavd, rusty, flash)
- `scx_sched_props`: SCX scheduler mode (options: default, gaming, power, latency, server)
- `vcache_mode`: VCache management mode (options: none, cache, freq)
- `profile_mode`: What type of device is in use, none means desktop (options: none, handheld, htpc)
## Profile Modes
Falcond now supports different profile modes for different device types:
- Default (none): Uses profiles from `/usr/share/falcond/profiles`
- Handheld: Uses profiles from `/usr/share/falcond/profiles/handheld`
- HTPC: Uses profiles from `/usr/share/falcond/profiles/htpc`
To set a profile mode, add this to your config file:
```
profile_mode = "handheld" # or "htpc" or "none"
```
## Game Profiles
Game profiles are stored in `/usr/share/falcond/profiles/` and define specific optimizations for individual games. You can contribute new profiles via PR at:
[Falcond Profiles Repository](https://github.com/PikaOS-Linux/falcond-profiles)
Example profile:
```
name = "game.exe"
performance_mode = true
scx_sched = bpfland
scx_sched_props = gaming
vcache_mode = cache
```
### Available Options
- `name`: The exe name (examples: cs2, PathOfExileSteam.exe)
- `performance_mode`: Enable/disable performance mode (default: true)
- `scx_sched`: SCX scheduler (options: none, bpfland, lavd, rusty, flash)
- `scx_sched_props`: SCX scheduler mode (options: none, gaming, power, latency, server)
- `vcache_mode`: VCache management mode (options: none, cache, freq)
## Service Management
To restart the daemon:
```bash
sudo systemctl restart falcond
```
To check the status:
```
sudo systemctl status falcond
```
## Source Code
The source code for falcond can be found at:
[Falcond Source Repository](https://git.pika-os.com/general-packages/falcond)
## Important Notes
⚠️ **Compatibility Warning** ⚠️ falcond should not be used alongside Feral GameMode or Falcon GameMode as they may conflict with each other. falcond provides similar functionality with additional features and optimizations.
## Why falcond?
Traditional gaming on Linux often requires manual optimization for each game - tweaking CPU governors, scheduling priorities, and cache settings. falcond automates this entire process by:
1. Automatically detecting when games are running
2. Applying optimized settings based on pre-configured profiles
3. Reverting settings when games are closed
4. Providing a centralized way to manage gaming performance
5. Easy switching of options for different device types
This means you can focus on gaming while falcond handles all the technical optimizations in the background!
## License
falcond is released under the [MIT License](http://git.pika-os.com/general-packages/falcond/raw/branch/main/LICENSE).
## Contributing
Please fork the [PikaOS-Linux/falcond](https://github.com/PikaOS-Linux/falcond) repository and submit a pull request.
## Build Dependencies
zig 0.14.0+
## Building from Source
```
git clone https://git.pika-os.com/general-packages/falcond.git
cd falcond
cd falcond
zig build -Doptimize=ReleaseFast
```
## Runtime Dependencies
These should be feature detected by falcond so if not present that specific feature will not be used.
power-profiles-daemon or tuned + tuned-ppd
scx-sched
Linux kernel patched with AMD 3D vcache support
## Packaging
falcond should be placed in /usr/bin/falcond and run via a service file. There is an example systemd service file in ./falcond/debian/falcond.service
falcond needs profiles to be useful, these should be placed in /usr/share/falcond/profiles alongside the system.conf in /usr/share/falcond/system.conf. Upto date profiles can be found in the [PikaOS-Linux/falcond-profiles](https://github.com/PikaOS-Linux/falcond-profiles) repository. We currently pull the latest profiles from there on building of this package but you could also package seperately and depend on that package.
There is a config file in /etc/falcond/config.conf which is generated automatically on first run. You could also package that if you need different default settings.

View File

@ -1,15 +1,3 @@
falcond (1.0.8-101pika2) pika; urgency=low
* Fix scx scheduler mode selection order
-- ferreo <ferreo@pika-os.com> Sun, 12 Jan 2025 13:48:00 +0300
falcond (1.0.7-101pika2) pika; urgency=low
* Don't load profiles in subfolders
-- ferreo <ferreo@pika-os.com> Sun, 12 Jan 2025 13:48:00 +0300
falcond (1.0.6-101pika1) pika; urgency=low
* Add handheld and htpc profiles, split system processes config to live in the profiles repo for easier updates

View File

@ -75,11 +75,7 @@ pub fn init(alloc: std.mem.Allocator) !void {
allocator = alloc;
std.log.info("Initializing scheduler state", .{});
const sched_list = getSupportedSchedulers(alloc) catch |err| {
std.log.warn("Failed to get supported schedulers: {}, scx_loader may not be available", .{err});
supported_schedulers = &[_]ScxScheduler{};
return;
};
const sched_list = try getSupportedSchedulers(alloc);
defer alloc.free(sched_list);
std.log.info("Supported schedulers:", .{});
@ -106,8 +102,8 @@ const SCX_IFACE = "org.scx.Loader";
fn modeToInt(mode: ScxSchedModes) u32 {
return switch (mode) {
.default => 0,
.gaming => 1,
.power => 2,
.power => 1,
.gaming => 2,
.latency => 3,
.server => 4,
};
@ -116,8 +112,8 @@ fn modeToInt(mode: ScxSchedModes) u32 {
fn intToMode(value: u32) ScxError!ScxSchedModes {
return switch (value) {
0 => .default,
1 => .gaming,
2 => .power,
1 => .power,
2 => .gaming,
3 => .latency,
4 => .server,
else => error.InvalidValue,
@ -127,38 +123,23 @@ fn intToMode(value: u32) ScxError!ScxSchedModes {
pub fn getCurrentScheduler(alloc: std.mem.Allocator) !?ScxScheduler {
var dbus_conn = dbus.DBus.init(alloc, SCX_NAME, SCX_PATH, SCX_IFACE);
const current = dbus_conn.getProperty("CurrentScheduler") catch |err| {
std.log.warn("Failed to get current scheduler: {}", .{err});
return .none;
};
const current = try dbus_conn.getProperty("CurrentScheduler");
defer alloc.free(current);
if (current.len == 0) return .none;
return ScxScheduler.fromString(current) catch |err| {
std.log.warn("Invalid scheduler value: {}", .{err});
return .none;
};
if (current.len == 0) return null;
return try ScxScheduler.fromString(current);
}
pub fn getCurrentMode(alloc: std.mem.Allocator) !ScxSchedModes {
var dbus_conn = dbus.DBus.init(alloc, SCX_NAME, SCX_PATH, SCX_IFACE);
const mode_str = dbus_conn.getProperty("SchedulerMode") catch |err| {
std.log.warn("Failed to get scheduler mode: {}", .{err});
return .default;
};
const mode_str = try dbus_conn.getProperty("SchedulerMode");
defer alloc.free(mode_str);
if (mode_str.len == 0) return .default;
const mode = std.fmt.parseInt(u32, mode_str, 10) catch |err| {
std.log.warn("Invalid scheduler mode value: {}", .{err});
return .default;
};
return intToMode(mode) catch |err| {
std.log.warn("Invalid mode value: {}", .{err});
return .default;
};
const mode = try std.fmt.parseInt(u32, mode_str, 10);
return intToMode(mode);
}
pub fn getSupportedSchedulers(alloc: std.mem.Allocator) ![]ScxScheduler {
@ -266,21 +247,23 @@ fn runSystemCtl(alloc: std.mem.Allocator, command: []const u8, service: []const
.allocator = alloc,
.argv = &argv,
.max_output_bytes = max_output_size,
}) catch {
}) catch |err| {
std.log.warn("Failed to run systemctl {s} {s}: {}", .{ command, service, err });
return;
};
defer alloc.free(result.stderr);
defer alloc.free(result.stdout);
if (result.term.Exited != 0) {
std.log.warn("systemctl failed: {s}", .{result.stderr});
return;
}
}
pub fn deactivateScheduler(alloc: std.mem.Allocator) ScxError!void {
runSystemCtl(alloc, "start", "ananicy-cpp");
var dbus_conn = dbus.DBus.init(alloc, SCX_NAME, SCX_PATH, SCX_IFACE);
try dbus_conn.callMethod("StopScheduler", &[_][]const u8{});
runSystemCtl(alloc, "start", "ananicy-cpp");
}
pub fn restorePreviousState(alloc: std.mem.Allocator) void {

View File

@ -30,10 +30,12 @@ pub fn loadConfDir(comptime T: type, allocator: std.mem.Allocator, dir_path: []c
var dir = try std.fs.openDirAbsolute(dir_path, .{ .iterate = true });
defer dir.close();
var iter = dir.iterate();
while (try iter.next()) |entry| {
if (entry.kind == .file and std.mem.endsWith(u8, entry.name, ".conf")) {
const path = try std.fs.path.join(allocator, &.{ dir_path, entry.name });
var walker = try dir.walk(allocator);
defer walker.deinit();
while (try walker.next()) |entry| {
if (entry.kind == .file and std.mem.endsWith(u8, entry.path, ".conf")) {
const path = try std.fs.path.join(allocator, &.{ dir_path, entry.path });
defer allocator.free(path);
const file = try std.fs.openFileAbsolute(path, .{});

View File

@ -288,7 +288,7 @@ pub fn Parser(comptime T: type) type {
}
},
.pointer => |ptr_info| {
if (ptr_info.size != .many) return error.InvalidSyntax;
if (ptr_info.size != .Slice) return error.InvalidSyntax;
switch (ptr_info.child) {
u8 => {
@field(result, field.name) = try self.parseString();

View File

@ -2,7 +2,7 @@
set -e
VERSION="1.0.8"
VERSION="1.0.6"
source ./pika-build-config.sh