@@ -71,6 +71,8 @@ namespace gui::utils
7171 }
7272
7373 const std::vector<u8 > data = vdf.to_vector <u8 >();
74+ vdf.close ();
75+
7476 usz last_pos = 0 ;
7577 usz pos = 0 ;
7678
@@ -500,9 +502,17 @@ namespace gui::utils
500502 sys_log.success (" Removed steam shortcut(s) for '%s'" , entry.app_name );
501503 }
502504
505+ update_steam_input_config (user_dir);
506+
503507 return true ;
504508 }
505509
510+ bool steam_shortcut::steam_installed ()
511+ {
512+ const std::string path = get_steam_path ();
513+ return !path.empty () && fs::is_dir (path);
514+ }
515+
506516 u32 steam_shortcut::crc32 (const std::string& data)
507517 {
508518 u32 crc = 0xFFFFFFFF ;
@@ -520,12 +530,6 @@ namespace gui::utils
520530 return ~crc;
521531 }
522532
523- bool steam_shortcut::steam_installed ()
524- {
525- const std::string path = get_steam_path ();
526- return !path.empty () && fs::is_dir (path);
527- }
528-
529533 u32 steam_shortcut::steam_appid (const std::string& exe, const std::string& name)
530534 {
531535 return crc32 (exe + name) | 0x80000000 ;
@@ -660,8 +664,171 @@ namespace gui::utils
660664 return str;
661665 }
662666
667+ void steam_shortcut::update_steam_input_config (const std::string& user_dir)
668+ {
669+ if (m_entries_to_add.empty () && m_entries_to_remove.empty ())
670+ {
671+ return ;
672+ }
673+
674+ const std::string vdf_path = user_dir + " localconfig.vdf" ;
675+ const std::string backup_path = fs::get_config_dir () + " /localconfig.vdf.backup" ;
676+
677+ if (fs::is_file (vdf_path) && !fs::copy_file (vdf_path, backup_path, true ))
678+ {
679+ sys_log.error (" Failed to backup steam localconfig file '%s'" , vdf_path);
680+ return ;
681+ }
682+
683+ fs::file vdf (vdf_path);
684+ if (!vdf)
685+ {
686+ sys_log.error (" update_steam_input_config: Failed to open steam localconfig file '%s': %s" , vdf_path, fs::g_tls_error);
687+ return ;
688+ }
689+
690+ std::string content = vdf.to_string ();
691+ vdf.close ();
692+
693+ static const std::string app_section_start = " \n\t\" apps\"\n\t {" ;
694+ static const std::string app_section_end = " \n\t }\n " ;
695+ static const std::string entry_section_end = " \n\t\t }" ;
696+
697+ bool nothing_to_remove = m_entries_to_remove.empty ();
698+
699+ usz app_pos = content.rfind (app_section_start);
700+ if (app_pos == umax)
701+ {
702+ if (!nothing_to_remove)
703+ {
704+ // We don't have to remove anything because this section did not exist
705+ sys_log.notice (" update_steam_input_config: Could not find \" apps\" section. No need to remove anything." );
706+ nothing_to_remove = true ;
707+ }
708+
709+ if (m_entries_to_add.empty ())
710+ {
711+ return ; // Nothing to do anyway
712+ }
713+
714+ const usz insert_pos = content.rfind (" \n }" );
715+ if (insert_pos == umax)
716+ {
717+ sys_log.error (" update_steam_input_config: Could not find main section end" );
718+ return ;
719+ }
720+
721+ sys_log.notice (" update_steam_input_config: Inserting missing \" apps\" section" );
722+ content.insert (insert_pos, fmt::format (" %s\n\t }" , app_section_start));
723+
724+ app_pos = content.rfind (app_section_start);
725+ ensure (app_pos != umax);
726+ }
727+
728+ const usz search_start = app_pos + app_section_start.size ();
729+
730+ const usz insert_pos = content.find (app_section_end, search_start);
731+ if (insert_pos == umax)
732+ {
733+ sys_log.error (" update_steam_input_config: Could not find apps section end" );
734+ return ;
735+ }
736+
737+ const auto appid_string = [](s32 signed_appid)
738+ {
739+ return fmt::format (" \n\t\t\" %d\"\n " , signed_appid);
740+ };
741+
742+ const auto find_entry = [&content, &appid_string, search_start, insert_pos](s32 signed_appid) -> usz
743+ {
744+ const usz pos = content.find (appid_string (signed_appid), search_start);
745+ if (pos >= insert_pos) return umax;
746+ return pos;
747+ };
748+
749+ bool dirty = false ;
750+
751+ // for (const shortcut_entry& entry : m_entries_to_remove)
752+ // {
753+ // if (nothing_to_remove)
754+ // {
755+ // break;
756+ // }
757+
758+ // const s32 signed_appid = static_cast<s32>(entry.appid);
759+ // const usz pos = find_entry(signed_appid);
760+
761+ // if (pos == umax)
762+ // {
763+ // // does not exist, do nothing
764+ // sys_log.notice("update_steam_input_config: Entry for '%s' with appid '%d' does not exist. Skipping removal", entry.app_name, signed_appid);
765+ // continue;
766+ // }
767+
768+ // // Find the opening brace of this entry
769+ // const usz pos_brace_open = content.find('{', pos);
770+ // if (pos_brace_open == umax || pos_brace_open >= insert_pos)
771+ // {
772+ // sys_log.error("update_steam_input_config: Can't find opening brace for entry for '%s' with appid '%d'.", entry.app_name, signed_appid);
773+ // continue;
774+ // }
775+
776+ // // Find the closing brace
777+ // const usz pos_brace_close = content.find(entry_section_end, pos_brace_open);
778+ // if (pos_brace_close == umax || pos_brace_close >= insert_pos)
779+ // {
780+ // sys_log.error("update_steam_input_config: Can't find closing brace for entry for '%s' with appid '%d'.", entry.app_name, signed_appid);
781+ // continue;
782+ // }
783+
784+ // // Include the closing brace line
785+ // const usz erase_end = pos_brace_close + entry_section_end.size();
786+
787+ // // Erase the whole block
788+ // content.erase(pos, erase_end - pos);
789+
790+ // sys_log.notice("update_steam_input_config: Removed '%s' with appid '%d'", entry.app_name, signed_appid);
791+
792+ // dirty = true;
793+ // }
794+
795+ for (const shortcut_entry& entry : m_entries_to_add)
796+ {
797+ const s32 signed_appid = static_cast <s32>(entry.appid );
798+ const usz pos = find_entry (signed_appid);
799+
800+ if (pos != umax)
801+ {
802+ // already exists, do nothing
803+ sys_log.notice (" update_steam_input_config: Entry for '%s' with appid '%d' already exists" , entry.app_name , signed_appid);
804+ continue ;
805+ }
806+
807+ sys_log.notice (" update_steam_input_config: Inserting '%s' with appid '%d'" , entry.app_name , signed_appid);
808+ content.insert (insert_pos, fmt::format (
809+ " %s"
810+ " \t\t {\n "
811+ " \t\t\t\" UseSteamControllerConfig\"\t\t\" 0\"\n "
812+ // "\t\t\t\"SteamControllerRumble\"\t\t\"-1\"\n"
813+ // "\t\t\t\"SteamControllerRumbleIntensity\"\t\t\"320\"\n"
814+ " \t\t }" , appid_string (signed_appid)));
815+
816+ dirty = true ;
817+ }
818+
819+ if (dirty && !fs::write_file (vdf_path, fs::rewrite, content))
820+ {
821+ sys_log.error (" Failed to update steam localconfig '%s': '%s'" , vdf_path, fs::g_tls_error);
822+
823+ if (!fs::copy_file (backup_path, vdf_path, true ))
824+ {
825+ sys_log.error (" Failed to restore steam localconfig backup: '%s'" , fs::g_tls_error);
826+ }
827+ }
828+ }
829+
663830#ifdef _WIN32
664- std::string get_registry_string (const wchar_t * key, const wchar_t * name)
831+ static std::string get_registry_string (const wchar_t * key, const wchar_t * name)
665832 {
666833 HKEY hkey = NULL ;
667834 LSTATUS status = RegOpenKeyW (HKEY_CURRENT_USER , key, &hkey);
@@ -825,6 +992,7 @@ namespace gui::utils
825992 // }
826993
827994 const std::string content = vdf.to_string ();
995+ vdf.close ();
828996
829997 usz user_count = 0 ;
830998
0 commit comments