summaryrefslogtreecommitdiff
path: root/src/config.cpp
diff options
context:
space:
mode:
authoraura <nw@moneybot.cc>2026-07-13 10:15:03 +0200
committeraura <nw@moneybot.cc>2026-07-13 10:15:03 +0200
commit57d172df4db1451ba3caeeb0ca485d0845a61912 (patch)
treead0be7c8bec79a1eb58b25f2a631bc4b6809e7fd /src/config.cpp
push source
Diffstat (limited to 'src/config.cpp')
-rw-r--r--src/config.cpp180
1 files changed, 180 insertions, 0 deletions
diff --git a/src/config.cpp b/src/config.cpp
new file mode 100644
index 0000000..22ea4aa
--- /dev/null
+++ b/src/config.cpp
@@ -0,0 +1,180 @@
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+
+const char DEFAULT_CONFIG[] =
+ "# fhvkov - forza horizon overlay (vulkan layer)\n"
+ "# positions and sizes are fractions of the game window;\n"
+ "# _x/_y are gauge centers. this file is re-read every second,\n"
+ "# so you can edit and save while driving.\n"
+ "port=9999\n"
+ "units=kmh\n"
+ "keep=0\n"
+ "scale=1.0\n"
+ "# needle motion blur: seconds of smear (try 0.06-0.15), 0 = off\n"
+ "blur=0.10\n"
+ "\n"
+ "tach_x=0.878\n"
+ "tach_y=0.830\n"
+ "tach_r=0.130\n"
+ "flash_needle=1\n"
+ "# whether to scale max rpm based on rpm reached by car\n"
+ "autoscale_rpm=1\n"
+ "# offset from max rpm at which needle starts flashing red\n"
+ "rpm_off=800.0\n"
+ "\n"
+ "show_boost=1\n"
+ "boost_x=0.775\n"
+ "boost_y=0.907\n"
+ "boost_r=0.060\n"
+ "\n"
+ "# lamps: abs, tcs (wheel slip) and tcs launch-control flash\n"
+ "show_abs=1\n"
+ "show_tcs=0\n"
+ "# enabling LC shows the \"tcs\" lamp\n"
+ "show_lc=1\n"
+ "show_tires=1\n"
+ "tire_x=0.970\n"
+ "tire_y=0.710\n"
+ "tire_sc=1.0\n";
+
+void config_defaults( CONFIG* c ) {
+ c->port = 9999;
+ c->units = 0;
+ c->keep = 0;
+ c->tach_x = 0.878; c->tach_y = 0.830; c->tach_r = 0.130;
+ c->scale = 1.0;
+ c->blur = 0.10;
+ c->show_boost = 1;
+ c->boost_x = 0.775; c->boost_y = 0.907; c->boost_r = 0.060;
+ c->show_abs = 1; c->show_tcs = 1; c->show_lc = 1;
+ c->show_tires = 1;
+ c->tire_x = 0.97; c->tire_y = 0.71, c->tire_sc = 1.0;
+ c->flash_needle = 1;
+ c->autoscale_rpm = 1;
+ c->rpm_off = 800.0;
+}
+
+void config_resolve_path( CONFIG* c ) {
+ const char* env = getenv( "FHRPM_CONFIG" );
+ if( env ) {
+ snprintf( c->path, sizeof( c->path ), "%s", env );
+ return;
+ }
+ const char* home = getenv( "HOME" );
+ if( !home )
+ home = ".";
+ snprintf( c->path, sizeof( c->path ), "%s/.config/fhvkov/fhvkov.conf", home );
+}
+
+void config_write_default( const CONFIG* c ) {
+ char dir[512];
+ const char* home = getenv( "HOME" );
+ if( home ) {
+ snprintf( dir, sizeof( dir ), "%s/.config", home );
+ mkdir( dir, 0755 );
+ snprintf( dir, sizeof( dir ), "%s/.config/fhvkov", home );
+ mkdir( dir, 0755 );
+ }
+
+ FILE* f = fopen( c->path, "w" );
+ if( !f )
+ return;
+ defer( fclose( f ) );
+
+ fwrite( DEFAULT_CONFIG, 1, sizeof( DEFAULT_CONFIG ) - 1, f );
+ dlog( "fhvkov: wrote default config to %s\n", c->path );
+}
+
+void config_parse_line( CONFIG* c, char* key, char* val ) {
+ if( !strcmp( key, "port" ) ) c->port = atoi( val );
+ else if( !strcmp( key, "units" ) ) c->units = !strcmp( val, "mph" );
+ else if( !strcmp( key, "keep" ) ) c->keep = atoi( val );
+ else if( !strcmp( key, "tach_x" ) ) c->tach_x = atof( val );
+ else if( !strcmp( key, "tach_y" ) ) c->tach_y = atof( val );
+ else if( !strcmp( key, "tach_r" ) ) c->tach_r = atof( val );
+ else if( !strcmp( key, "show_boost" ) ) c->show_boost = atoi( val );
+ else if( !strcmp( key, "boost_x" ) ) c->boost_x = atof( val );
+ else if( !strcmp( key, "boost_y" ) ) c->boost_y = atof( val );
+ else if( !strcmp( key, "boost_r" ) ) c->boost_r = atof( val );
+ else if( !strcmp( key, "scale" ) ) c->scale = atof( val );
+ else if( !strcmp( key, "blur" ) ) c->blur = atof( val );
+ else if( !strcmp( key, "show_abs" ) ) c->show_abs = atoi( val );
+ else if( !strcmp( key, "show_tcs" ) ) c->show_tcs = atoi( val );
+ else if( !strcmp( key, "show_lc" ) ) c->show_lc = atoi( val );
+ else if( !strcmp( key, "show_tires" ) ) c->show_tires = atoi( val );
+ else if( !strcmp( key, "tire_x" ) ) c->tire_x = atof( val );
+ else if( !strcmp( key, "tire_y" ) ) c->tire_y = atof( val );
+ else if( !strcmp( key, "tire_sc" ) ) c->tire_sc = atof( val );
+ else if( !strcmp( key, "flash_needle" ) ) c->flash_needle = atoi( val );
+ else if( !strcmp( key, "autoscale_rpm" ) ) c->autoscale_rpm = atoi( val );
+ else if( !strcmp( key, "rpm_off" ) ) c->rpm_off = atof( val );
+}
+
+STAT config_load( CONFIG* c ) {
+ FILE* f = fopen( c->path, "r" );
+ if( !f )
+ return STAT_ERR;
+ defer( fclose( f ) );
+
+ char line[256];
+ while( fgets( line, sizeof( line ), f ) ) {
+ char* p = line;
+ while( *p == ' ' || *p == '\t' )
+ p++;
+ if( *p == '#' || *p == '\n' ||* p == 0 )
+ continue;
+
+ char* eq = strchr( p, '=' );
+ if( !eq )
+ continue;
+ *eq = 0;
+
+ char* key = p, *val = eq + 1;
+ char* nl = strchr( val, '\n' );
+ if( nl )
+ *nl = 0;
+ char* e = key + strlen( key );
+ while( e > key && ( e[-1] == ' ' || e[-1] == '\t' ) )
+ *--e = 0;
+
+ config_parse_line( c, key, val );
+ }
+
+ struct stat st;
+ if( stat( c->path, &st ) == 0 )
+ c->mtime = st.st_mtime;
+ return STAT_OK;
+}
+
+void config_init( CONFIG* c ) {
+ config_defaults( c );
+ config_resolve_path( c );
+ if( !OK( config_load( c ) ) ) {
+ config_write_default( c );
+ config_load( c );
+ }
+}
+
+U8 config_poll( CONFIG* c ) {
+ struct stat st;
+ if( stat( c->path, &st ) != 0 )
+ return 0;
+ if( st.st_mtime == c->mtime )
+ return 0;
+
+ CONFIG fresh;
+ config_defaults( &fresh );
+ memcpy( fresh.path, c->path, sizeof( fresh.path ) );
+ if( !OK( config_load( &fresh ) ) )
+ return 0;
+
+ fresh.port = c->port;
+ *c = fresh;
+ dlog( "fhvkov: config reloaded\n" );
+ return 1;
+}