diff --git a/Readme_release.txt b/Readme_release.txt index 2abd87c..582dcb5 100644 --- a/Readme_release.txt +++ b/Readme_release.txt @@ -33,11 +33,17 @@ Note that this save directory will be beside where the emu dll (or .so) is which DLC: By default the emulator will try to unlock all DLCs (by returning true when the game calls the BIsDlcInstalled function). If the game uses the other function you will need to provide a list of DLCs to my emulator. To do this first create a steam_settings folder right beside where you put my emulator. -In this folder, put a DLC.txt file. (path will be \steam_settings\DLC.txt) +In this folder, put a DLC.txt file. (path will be \steam_settings\DLC.txt) If the DLC file is present, the emulator will only unlock the DLCs in that file. If the file is empty all DLCs will be locked. The contents of this file are: appid=DLC name See the steam_settings.EXAMPLE folder for an example. +App paths: +Some rare games might need to be provided one or more paths to app ids. For example the path to where a dlc is installed. This sets the paths returned by the Steam_Apps::GetAppInstallDir function. +See steam_settings.EXAMPLE\app_paths.EXAMPLE.txt for an example. +This file should be put here: \steam_settings\app_paths.txt +Note that paths are treated as relative paths from where the steam_api dll is located. + Mods: Put your mods in the steam_settings\mods\ folder. The steam_settings folder must be placed right beside my emulator dll. Mod folders must be a number corresponding to the file id of the mod. diff --git a/dll/base.cpp b/dll/base.cpp index 73613ab..e2d1c9b 100644 --- a/dll/base.cpp +++ b/dll/base.cpp @@ -19,6 +19,7 @@ #ifdef STEAM_WIN32 #include +#include #define SystemFunction036 NTAPI SystemFunction036 #include @@ -39,7 +40,7 @@ std::string get_env_variable(std::string name) return std::string(); } - env_variable[ret - 1] = 0; + env_variable[ret] = 0; return std::string(env_variable); } @@ -204,6 +205,40 @@ std::string get_full_program_path() return program_path; } +std::string get_current_path() +{ + std::string path; +#if defined(STEAM_WIN32) + char *buffer = _getcwd( NULL, 0 ); +#else + char *buffer = get_current_dir_name(); +#endif + if (buffer) { + path = buffer; + path.append(PATH_SEPARATOR); + free(buffer); + } + + return path; +} + +std::string canonical_path(std::string path) +{ + std::string output; +#if defined(STEAM_WIN32) + char *buffer = _fullpath(NULL, path.c_str(), 0); +#else + char *buffer = canonicalize_file_name(path.c_str()); +#endif + + if (buffer) { + output = buffer; + free(buffer); + } + + return output; +} + static void steam_auth_ticket_callback(void *object, Common_Message *msg) { PRINT_DEBUG("steam_auth_ticket_callback\n"); diff --git a/dll/base.h b/dll/base.h index 2f43f8e..7e08258 100644 --- a/dll/base.h +++ b/dll/base.h @@ -135,6 +135,8 @@ CSteamID generate_steam_id_server(); CSteamID generate_steam_id_anonserver(); CSteamID generate_steam_id_lobby(); std::string get_full_program_path(); +std::string get_current_path(); +std::string canonical_path(std::string path); class SteamCallResults { std::vector callresults; diff --git a/dll/settings.cpp b/dll/settings.cpp index a14bd36..f71f588 100644 --- a/dll/settings.cpp +++ b/dll/settings.cpp @@ -184,3 +184,13 @@ bool Settings::getDLC(unsigned int index, AppId_t &appID, bool &available, std:: name = DLCs[index].name; return true; } + +void Settings::setAppInstallPath(AppId_t appID, std::string path) +{ + app_paths[appID] = path; +} + +std::string Settings::getAppInstallPath(AppId_t appID) +{ + return app_paths[appID]; +} diff --git a/dll/settings.h b/dll/settings.h index c7daadb..001b7ef 100644 --- a/dll/settings.h +++ b/dll/settings.h @@ -43,6 +43,8 @@ class Settings { bool offline; std::vector DLCs; std::vector mods; + std::map app_paths; + public: #ifdef LOBBY_CONNECT static const bool is_lobby_connect = true; @@ -67,6 +69,10 @@ public: bool hasDLC(AppId_t appID); bool getDLC(unsigned int index, AppId_t &appID, bool &available, std::string &name); + //App Install paths + void setAppInstallPath(AppId_t appID, std::string path); + std::string getAppInstallPath(AppId_t appID); + //mod stuff void addMod(PublishedFileId_t id, std::string title, std::string path); Mod_entry getMod(PublishedFileId_t id); diff --git a/dll/steam_apps.cpp b/dll/steam_apps.cpp index caf7ffa..794e35e 100644 --- a/dll/steam_apps.cpp +++ b/dll/steam_apps.cpp @@ -188,11 +188,26 @@ uint32 Steam_Apps::GetInstalledDepots( AppId_t appID, DepotId_t *pvecDepots, uin // returns current app install folder for AppID, returns folder name length uint32 Steam_Apps::GetAppInstallDir( AppId_t appID, char *pchFolder, uint32 cchFolderBufferSize ) { - PRINT_DEBUG("GetAppInstallDir %u\n", cchFolderBufferSize); + PRINT_DEBUG("GetAppInstallDir %u %u\n", appID, cchFolderBufferSize); //TODO return real path instead of dll path if (!pchFolder || !cchFolderBufferSize) return 0; - std::string path = get_full_program_path(); - snprintf(pchFolder, cchFolderBufferSize, "%s", path.c_str()); + std::string installed_path = settings->getAppInstallPath(appID); + + if (installed_path.size() == 0) { + std::string dll_path = get_full_program_path(); + std::string current_path = get_current_path(); + PRINT_DEBUG("paths %s %s\n", dll_path.c_str(), current_path.c_str()); + + //Just pick the smallest path, it has the most chances of being the good one + if (dll_path.size() > current_path.size() && current_path.size()) { + installed_path = current_path; + } else { + installed_path = dll_path; + } + } + + PRINT_DEBUG("path %s\n", installed_path.c_str()); + snprintf(pchFolder, cchFolderBufferSize, "%s", installed_path.c_str()); return strlen(pchFolder); } diff --git a/dll/steam_client.cpp b/dll/steam_client.cpp index 0602432..d608ef8 100644 --- a/dll/steam_client.cpp +++ b/dll/steam_client.cpp @@ -211,6 +211,7 @@ Steam_Client::Steam_Client() std::ifstream input( dlc_config_path ); if (input.is_open()) { settings_client->unlockAllDLC(false); + settings_server->unlockAllDLC(false); PRINT_DEBUG("Locking all DLC\n"); for( std::string line; getline( input, line ); ) { @@ -243,6 +244,39 @@ Steam_Client::Steam_Client() } } + { + std::string dlc_config_path = Local_Storage::get_game_settings_path() + "app_paths.txt"; + std::ifstream input( dlc_config_path ); + if (input.is_open()) { + for( std::string line; getline( input, line ); ) { + if (!line.empty() && line[line.length()-1] == '\n') { + line.erase(line.length()-1); + } + + if (!line.empty() && line[line.length()-1] == '\r') { + line.erase(line.length()-1); + } + + std::size_t deliminator = line.find("="); + if (deliminator != 0 && deliminator != std::string::npos && deliminator != line.size()) { + AppId_t appid = stol(line.substr(0, deliminator)); + std::string rel_path = line.substr(deliminator + 1); + std::string path = canonical_path(program_path + rel_path); + + if (appid) { + if (path.size()) { + PRINT_DEBUG("Adding app path: %u|%s|\n", appid, path.c_str()); + settings_client->setAppInstallPath(appid, path); + settings_server->setAppInstallPath(appid, path); + } else { + PRINT_DEBUG("Error adding app path for: %u does this path exist? |%s|\n", appid, rel_path.c_str()); + } + } + } + } + } + } + { std::string mod_path = Local_Storage::get_game_settings_path() + "mods"; std::vector paths = Local_Storage::get_filenames_path(mod_path); diff --git a/files_example/steam_settings.EXAMPLE/app_paths.EXAMPLE.txt b/files_example/steam_settings.EXAMPLE/app_paths.EXAMPLE.txt new file mode 100644 index 0000000..c75f4b3 --- /dev/null +++ b/files_example/steam_settings.EXAMPLE/app_paths.EXAMPLE.txt @@ -0,0 +1,4 @@ +556760=../DLCRoot0 +1234=./folder_where_steam_api_is +3456=../folder_one_level_above_where_steam_api_is +5678=../../folder_two_levels_above_where_steam_api_is