Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/core/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ void Loader::ReadBasicConfig()
linb::ini data;

Log("Loading basic config file %s", basicConfig.c_str());
if(data.load_file(gamePath + basicConfig))
if(data.load_file(modloaderPath + basicConfig))
{
// Read basic stuff from [Config] section
for(auto& pair : data["Config"])
Expand Down Expand Up @@ -62,7 +62,7 @@ void Loader::ReadBasicConfig()
config["AutoRefresh"] = modloader::to_string(bAutoRefresh);

// Log only about failure since we'll be saving every time a entry on the menu changes
if(!ini.write_file(gamePath + basicConfig))
if(!ini.write_file(modloaderPath + basicConfig))
Log("Failed to save basic config file");
}

Expand Down Expand Up @@ -224,7 +224,7 @@ void Loader::UpdateOldConfig_0115_021()
newer[newsec.section] = old[oldsec.section];
};

if(old.load_file(gamePath + "/modloader/modloader.ini"))
if(old.load_file(modloaderPath + folderConfigFilename))
{
if(old.count("CONFIG") && old.count("PRIORITY"))
{
Expand All @@ -246,7 +246,7 @@ void Loader::UpdateOldConfig_0115_021()
kv.second = std::to_string(pr > 0 && pr <= limit? (limit + 1) - pr : pr);
}

newer.write_file(gamePath + "modloader/" + folderConfigFilename);
newer.write_file(modloaderPath + folderConfigFilename);
}
}
}
Expand Down Expand Up @@ -275,7 +275,7 @@ void Loader::UpdateOldConfig_023_024()
newer[newsec.section] = old[oldsec.section];
};

if(old.load_file(gamePath + "modloader/modloader.ini"))
if(old.load_file(modloaderPath + folderConfigFilename))
{
if(old.count("Config") && old.count("Priority"))
{
Expand All @@ -292,7 +292,7 @@ void Loader::UpdateOldConfig_023_024()
newer.set("Folder.Config", "Profile", "Default");
newer["Profiles.Default.ExclusiveMods"];

newer.write_file(gamePath + "modloader/" + folderConfigFilename);
newer.write_file(modloaderPath + folderConfigFilename);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/extras/gta3/menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ void TheMenu::LoadText()

auto LoadFXT = [this](uint32_t locale)
{
auto lang = loader.gamePath + loader.dataPath + "/text/" + std::to_string(locale) + "/menu.fxt";
auto lang = loader.modloaderPath + loader.dataPath + "text/" + std::to_string(locale) + "/menu.fxt";
return ParseFXT(fxt, lang.data());
};

Expand Down
4 changes: 2 additions & 2 deletions src/core/folder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ void Loader::FolderInformation::LoadConfigFromINI()
Log("Warning: Failed to load folder config file");

// Then from the profiles directory
if(MakeSureDirectoryExistA((loader.gamePath + loader.profilesPath).c_str()))
if(MakeSureDirectoryExistA((loader.modloaderPath + loader.profilesPath).c_str()))
{
::scoped_gdir xdir(loader.profilesPath.c_str());
for(auto& filename : FilesWalk("", "*.ini", false))
Expand Down Expand Up @@ -430,7 +430,7 @@ void Loader::FolderInformation::SaveConfigForINI()
// Profile direcly in modloader.ini
profile.SaveConfigForINI(ini);
}
else if(MakeSureDirectoryExistA((loader.gamePath + loader.profilesPath).c_str()))
else if(MakeSureDirectoryExistA((loader.modloaderPath + loader.profilesPath).c_str()))
{
// This profile has it's own directory
::scoped_gdir xdir(loader.profilesPath.c_str());
Expand Down
65 changes: 48 additions & 17 deletions src/core/loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ REGISTER_ML_NULL();

// Mod Loader object
Loader loader;
static HINSTANCE hLoaderModule = NULL;

static std::string MakePathRelativeTo(const std::string& path, const std::string& base)
{
if(path.size() >= base.size() && !_strnicmp(path.c_str(), base.c_str(), base.size()))
return path.substr(base.size());
return path;
}

/*
* DllMain
Expand All @@ -29,6 +37,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
if(fdwReason == DLL_PROCESS_ATTACH)
{
hLoaderModule = hinstDLL;
if(!loader.Patch())
return FALSE;
}
Expand Down Expand Up @@ -139,10 +148,27 @@ bool Loader::Patch()
void Loader::Startup()
{
char rootPath[MAX_PATH];
char moduleFilename[MAX_PATH];
char appDataPath[MAX_PATH];

// If not running yet and 'modloader' folder exists, let's start up
if(!this->bRunning && IsDirectoryA("modloader"))
GetCurrentDirectoryA(sizeof(rootPath), rootPath);
MakeSureStringIsDirectory(this->gamePath = rootPath);

if(hLoaderModule && GetModuleFileNameA(hLoaderModule, moduleFilename, sizeof(moduleFilename)))
{
this->modulePath = moduleFilename;
this->modulePath.erase(this->modulePath.find_last_of("\\/") + 1);
MakeSureStringIsDirectory(this->modulePath);
}
else
this->modulePath = this->gamePath;

std::string rootModloaderPath = this->gamePath + "modloader";
std::string moduleModloaderPath = this->modulePath + "modloader";

// If not running yet and a 'modloader' folder exists, let's start up.
// Prefer the ASI directory, then fall back to the traditional game root folder.
if(!this->bRunning && (IsDirectoryA(rootModloaderPath.c_str()) || IsDirectoryA(moduleModloaderPath.c_str())))
{
// Cleanup the base structure
memset(this, 0, sizeof(modloader_t));
Expand All @@ -157,14 +183,19 @@ void Loader::Startup()
this->maxBytesInLog = 5242880; // 5 MiB
this->currentModId = 0;
this->currentFileId = 0x8000000000000000; // File id should have the hibit set

// Open the log file
OpenLog();
LogGameVersion();

// Setup root path variables
GetCurrentDirectoryA(sizeof(rootPath), rootPath);
MakeSureStringIsDirectory(this->gamePath = rootPath);
MakeSureStringIsDirectory(this->modulePath);
this->modloaderPath = IsDirectoryA(moduleModloaderPath.c_str())? moduleModloaderPath : rootModloaderPath;
MakeSureStringIsDirectory(this->modloaderPath);
MakeSureStringIsDirectory(this->modloaderRelativePath = MakePathRelativeTo(this->modloaderPath, this->gamePath));
this->mods = FolderInformation(this->modloaderRelativePath);

// Open the log file
OpenLog();
LogGameVersion();
Log("Using Mod Loader folder \"%s\"", this->modloaderPath.c_str());

// Setup "%ProgramData%/modloader/" variable
if(SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_COMMON_APPDATA|CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, appDataPath)))
Expand All @@ -175,22 +206,22 @@ void Loader::Startup()
MakeSureStringIsDirectory(MakeSureStringIsDirectory(this->localAppDataPath = appDataPath).append("modloader"));

// Setup basic path variables
this->dataPath = "modloader/.data/";
this->pluginPath = "modloader/.data/plugins/";
this->profilesPath= "modloader/.profiles/";
this->dataPath = ".data/";
this->pluginPath = ".data/plugins/";
this->profilesPath= ".profiles/";

// Setup config file names
this->folderConfigFilename = "modloader.ini";
this->basicConfig = dataPath + "config.ini";
this->pluginConfigFilename = "plugins.ini";
this->folderConfigDefault = gamePath + dataPath + "modloader.ini.0";
this->basicConfigDefault = gamePath + dataPath + "config.ini.0";
this->pluginConfigDefault = gamePath + dataPath + "plugins.ini.0";
this->folderConfigDefault = modloaderPath + dataPath + "modloader.ini.0";
this->basicConfigDefault = modloaderPath + dataPath + "config.ini.0";
this->pluginConfigDefault = modloaderPath + dataPath + "plugins.ini.0";

// Make sure the important folders exist
if(!MakeSureDirectoryExistA(dataPath.c_str())
|| !MakeSureDirectoryExistA(profilesPath.c_str())
|| !MakeSureDirectoryExistA(pluginPath.c_str())
if(!MakeSureDirectoryExistA((modloaderPath + dataPath).c_str())
|| !MakeSureDirectoryExistA((modloaderPath + profilesPath).c_str())
|| !MakeSureDirectoryExistA((modloaderPath + pluginPath).c_str())
|| !MakeSureDirectoryExistA(commonAppDataPath.c_str())
|| !MakeSureDirectoryExistA(localAppDataPath.c_str()))
{
Expand Down Expand Up @@ -224,7 +255,7 @@ void Loader::Startup()
this->UpdateOldConfig();

// Load the basic configuration file
CopyFileA(basicConfigDefault.c_str(), basicConfig.c_str(), TRUE);
CopyFileA(basicConfigDefault.c_str(), (modloaderPath + basicConfig).c_str(), TRUE);
this->ReadBasicConfig();

// Check if logging is disabled by the basic config file
Expand Down
30 changes: 24 additions & 6 deletions src/core/loader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,7 @@ class Loader : public modloader_t
protected:
friend struct Updating;
friend struct scoped_gdir;
friend std::string GetGDirPath(const char* newdir);
friend class TheMenu;

uint32_t mUpdateRefCount = 0;
Expand All @@ -489,11 +490,14 @@ class Loader : public modloader_t

// Directories
std::string gamePath; // Full game path
std::string dataPath; // .data path
std::string profilesPath; // .profiles path
std::string modulePath; // Full path where modloader.asi is located
std::string modloaderPath; // Full path to the active modloader folder
std::string modloaderRelativePath; // Active modloader folder relative to game path when possible
std::string dataPath; // .data path, relative to modloader path
std::string profilesPath; // .profiles path, relative to modloader path
std::string commonAppDataPath; // for all users AppData path
std::string localAppDataPath; // for the current user AppData path
std::string pluginPath; // Plugins path (relative to game path)
std::string pluginPath; // Plugins path, relative to modloader path

std::string basicConfig;
std::string basicConfigDefault; // Full path for the default basic config file
Expand Down Expand Up @@ -551,8 +555,10 @@ class Loader : public modloader_t
public:

// Constructor
Loader() : mods("modloader")
Loader() : mods("")
{}

const std::string& GetModLoaderPath() const { return modloaderPath; }

// Patches the game code to run this core
bool Patch();
Expand Down Expand Up @@ -691,10 +697,22 @@ inline bool operator==(const Loader::PluginInformation& a, const Loader::PluginI
return (&a == &b);
}

// Scoped chdir relative to gamedir
inline std::string GetGDirPath(const char* newdir)
{
if(!newdir[0])
return loader.gamePath;
if(modloader::IsAbsolutePath(newdir))
return newdir;
if(loader.modloaderRelativePath.size()
&& !_strnicmp(newdir, loader.modloaderRelativePath.c_str(), loader.modloaderRelativePath.size()))
return loader.gamePath + newdir;
return loader.modloaderPath + newdir;
}

// Scoped chdir relative to active modloader dir, or gamedir for an empty path
struct scoped_gdir : public modloader::scoped_chdir
{
scoped_gdir(const char* newdir) : scoped_chdir((!newdir[0]? loader.gamePath : loader.gamePath + newdir).data())
scoped_gdir(const char* newdir) : scoped_chdir(GetGDirPath(newdir).data())
{ }
};

Expand Down
2 changes: 1 addition & 1 deletion src/core/logging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ void Loader::OpenLog()
void Loader::TruncateLog()
{
// Clears the ammount of bytes written...
auto path = this->gamePath + "modloader/modloader.log";
auto path = this->modloaderPath + "modloader.log";
numBytesInLog = 0;

if(logfile == nullptr)
Expand Down
2 changes: 1 addition & 1 deletion src/core/plugins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ bool Loader::LoadPlugin(std::string filename)


// Load the plugin module, use full path because we don't want to conflict with any other plugin with same name but different directory
if(module = LoadLibraryA((this->gamePath + this->pluginPath + modulename).c_str()))
if(module = LoadLibraryA((this->modloaderPath + this->pluginPath + modulename).c_str()))
{
Log("Loading plugin module \"%s\"", modulename);
auto GetLoaderVersion = (modloader_fGetLoaderVersion) GetProcAddress(module, "GetLoaderVersion");
Expand Down
4 changes: 2 additions & 2 deletions src/core/watcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ void Loader::StartupWatcher()
if(hCancelEvent)
{
// Takes up the directory handle for modloader...
hDirectory = CreateFileA((this->gamePath + "modloader/").c_str(),
hDirectory = CreateFileA(this->modloaderPath.c_str(),
FILE_LIST_DIRECTORY, (FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE),
NULL, OPEN_EXISTING, (FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED), NULL);
if(hDirectory != INVALID_HANDLE_VALUE)
Expand Down Expand Up @@ -373,7 +373,7 @@ static void NotifyJournal(std::string modname, int action, bool is_root)
{
// Something changed in the directory itself, not inside it

bool is_existing_directory = !!IsDirectoryA(std::string(loader.gamepath).append("modloader/").append(modname).c_str());
bool is_existing_directory = !!IsDirectoryA((loader.GetModLoaderPath() + modname).c_str());

if(action == FILE_ACTION_ADDED || action == FILE_ACTION_RENAMED_NEW_NAME)
AddToJournal(Loader::Status::Added);
Expand Down