mirror of
https://github.com/mon/ifs_layeredfs.git
synced 2026-04-25 15:57:45 -05:00
v2.2: fix winxp, support ifs-in-ifs
This commit is contained in:
parent
2ae0fee8be
commit
27af072b0d
|
|
@ -16,7 +16,6 @@ using std::string;
|
|||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <mutex>
|
||||
|
||||
#include "3rd_party/MinHook.h"
|
||||
#pragma comment(lib, "minhook.lib")
|
||||
|
|
@ -33,12 +32,13 @@ using std::string;
|
|||
//#include "jubeat.h"
|
||||
#include "texture_packer.h"
|
||||
#include "modpath_handler.h"
|
||||
#include "winxp_mutex.hpp"
|
||||
|
||||
// let me use the std:: version, damnit
|
||||
#undef max
|
||||
#undef min
|
||||
|
||||
#define VER_STRING "2.1"
|
||||
#define VER_STRING "2.2"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define DBG_VER_STRING "_DEBUG"
|
||||
|
|
@ -77,7 +77,7 @@ typedef struct image {
|
|||
|
||||
// ifs_textures["data/graphics/ver04/logo.ifs/tex/4f754d4f424f092637a49a5527ece9bb"] will be "konami"
|
||||
static std::unordered_map<string, image_t> ifs_textures;
|
||||
static std::mutex ifs_textures_mtx;
|
||||
static CriticalSectionLock ifs_textures_mtx;
|
||||
|
||||
typedef std::unordered_set<string> string_set;
|
||||
|
||||
|
|
@ -673,9 +673,8 @@ AVS_FILE hook_avs_fs_open(const char* name, uint16_t mode, int flags) {
|
|||
auto norm_path = *_norm_path;
|
||||
|
||||
auto mod_path = find_first_modfile(norm_path);
|
||||
if (!mod_path) {
|
||||
// mod ifs paths use _ifs
|
||||
string_replace(norm_path, ".ifs", "_ifs");
|
||||
// mod ifs paths use _ifs, go one at a time for ifs-inside-ifs
|
||||
while (!mod_path && string_replace_first(norm_path, ".ifs", "_ifs")) {
|
||||
mod_path = find_first_modfile(norm_path);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@
|
|||
<DebugInformationFormat>None</DebugInformationFormat>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalOptions>/Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
|
@ -146,6 +147,7 @@
|
|||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<DebugInformationFormat>None</DebugInformationFormat>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalOptions>/Zc:threadSafeInit-</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
|
@ -181,6 +183,7 @@
|
|||
<ClInclude Include="ramfs_demangler.h" />
|
||||
<ClInclude Include="texture_packer.h" />
|
||||
<ClInclude Include="utils.h" />
|
||||
<ClInclude Include="winxp_mutex.hpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="3rd_party\GuillotineBinPack.cpp" />
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <mutex>
|
||||
|
||||
#include "ramfs_demangler.h"
|
||||
|
||||
|
|
@ -10,6 +9,7 @@
|
|||
#include "config.hpp"
|
||||
#include "utils.h"
|
||||
#include "avs.h"
|
||||
#include "winxp_mutex.hpp"
|
||||
|
||||
using std::nullopt;
|
||||
|
||||
|
|
@ -80,7 +80,7 @@ void cache_mods(void) {
|
|||
// data, data2, data_op2 etc
|
||||
// data is "flat", all others must have their own special subfolders
|
||||
static vector<string> game_folders;
|
||||
static std::mutex game_folders_mtx;
|
||||
static CriticalSectionLock game_folders_mtx;
|
||||
|
||||
optional<string> normalise_path(string &path) {
|
||||
// one-off init
|
||||
|
|
@ -228,6 +228,7 @@ optional<string> find_first_cached_item(const string &norm_path) {
|
|||
}
|
||||
|
||||
optional<string> find_first_modfile(const string &norm_path) {
|
||||
//logf_verbose("%s(%s)", __FUNCTION__, norm_path.c_str());
|
||||
if (config.developer_mode) {
|
||||
for (auto &dir : available_mods()) {
|
||||
auto mod_path = dir + "/" + norm_path;
|
||||
|
|
|
|||
|
|
@ -32,13 +32,13 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
|
||||
#include "3rd_party/hat-trie/htrie_map.h"
|
||||
|
||||
#include "ramfs_demangler.h"
|
||||
#include "utils.h"
|
||||
#include "winxp_mutex.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
|
@ -56,14 +56,17 @@ static unordered_map<void*, string> ram_load_map;
|
|||
static tsl::htrie_map<char, string> ramfs_map;
|
||||
static tsl::htrie_map<char, string> mangling_map;
|
||||
|
||||
static std::mutex mangling_mtx;
|
||||
static CriticalSectionLock mangling_mtx;
|
||||
|
||||
// since we call this from a function that is already taking the lock
|
||||
static void ramfs_demangler_demangle_if_possible_nolock(std::string& raw_path);
|
||||
|
||||
void ramfs_demangler_on_fs_open(const std::string& norm_path, AVS_FILE open_result) {
|
||||
if (open_result < 0 || !string_ends_with(norm_path.c_str(), ".ifs")) {
|
||||
return;
|
||||
}
|
||||
|
||||
const std::lock_guard<std::mutex> lock(mangling_mtx);
|
||||
mangling_mtx.lock();
|
||||
|
||||
auto existing_info = cleanup_map.find(norm_path);
|
||||
if (existing_info != cleanup_map.end()) {
|
||||
|
|
@ -89,10 +92,12 @@ void ramfs_demangler_on_fs_open(const std::string& norm_path, AVS_FILE open_resu
|
|||
};
|
||||
cleanup_map[norm_path] = cleanup;
|
||||
open_file_map[open_result] = norm_path;
|
||||
|
||||
mangling_mtx.unlock();
|
||||
}
|
||||
|
||||
void ramfs_demangler_on_fs_read(AVS_FILE context, void* dest) {
|
||||
const std::lock_guard<std::mutex> lock(mangling_mtx);
|
||||
mangling_mtx.lock();
|
||||
|
||||
auto find = open_file_map.find(context);
|
||||
if (find != open_file_map.end()) {
|
||||
|
|
@ -106,26 +111,30 @@ void ramfs_demangler_on_fs_read(AVS_FILE context, void* dest) {
|
|||
cleanup->second.buffer = dest;
|
||||
}
|
||||
}
|
||||
|
||||
mangling_mtx.unlock();
|
||||
}
|
||||
|
||||
void ramfs_demangler_on_fs_mount(const char* mountpoint, const char* fsroot, const char* fstype, const char* flags) {
|
||||
const std::lock_guard<std::mutex> lock(mangling_mtx);
|
||||
mangling_mtx.lock();
|
||||
|
||||
if (!strcmp(fstype, "ramfs")) {
|
||||
void* buffer;
|
||||
|
||||
if (!flags) {
|
||||
logf_verbose("ramfs has no flags?");
|
||||
mangling_mtx.unlock();
|
||||
return;
|
||||
}
|
||||
const char* baseptr = strstr(flags, "base=");
|
||||
if (!baseptr) {
|
||||
logf_verbose("ramfs has no base pointer?");
|
||||
mangling_mtx.unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
buffer = (void*)strtoull(baseptr + strlen("base="), NULL, 0);
|
||||
|
||||
|
||||
auto find = ram_load_map.find(buffer);
|
||||
if (find != ram_load_map.end()) {
|
||||
auto orig_path = find->second;
|
||||
|
|
@ -152,18 +161,32 @@ void ramfs_demangler_on_fs_mount(const char* mountpoint, const char* fsroot, con
|
|||
}
|
||||
}
|
||||
else if(string_ends_with(fsroot, ".ifs")) {
|
||||
//logf_verbose("imagefs mount mapped to %s", fsroot);
|
||||
mangling_map[mountpoint] = (string)fsroot;
|
||||
// this fixes ifs-inside-ifs by demangling the root location too
|
||||
string root = (string)fsroot;
|
||||
ramfs_demangler_demangle_if_possible_nolock(root);
|
||||
logf_verbose("imagefs mount mapped to %s", root.c_str());
|
||||
mangling_map[mountpoint] = root;
|
||||
}
|
||||
}
|
||||
|
||||
mangling_mtx.unlock();
|
||||
}
|
||||
|
||||
void ramfs_demangler_demangle_if_possible(std::string& raw_path) {
|
||||
const std::lock_guard<std::mutex> lock(mangling_mtx);
|
||||
mangling_mtx.lock();
|
||||
|
||||
auto search = mangling_map.longest_prefix(raw_path);
|
||||
if (search != mangling_map.end()) {
|
||||
//logf_verbose("can demangle %s to %s", search.key().c_str(), search->c_str());
|
||||
string_replace(raw_path, search.key().c_str(), search->c_str());
|
||||
}
|
||||
}
|
||||
|
||||
mangling_mtx.unlock();
|
||||
}
|
||||
|
||||
static void ramfs_demangler_demangle_if_possible_nolock(std::string& raw_path) {
|
||||
auto search = mangling_map.longest_prefix(raw_path);
|
||||
if (search != mangling_map.end()) {
|
||||
string_replace(raw_path, search.key().c_str(), search->c_str());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
#include "utils.h"
|
||||
#include "avs.h"
|
||||
|
||||
#include <mutex>
|
||||
#include "winxp_mutex.hpp"
|
||||
|
||||
#define SUPPRESS_PRINTF
|
||||
|
||||
void logf(char* fmt, ...) {
|
||||
static std::mutex log_mutex;
|
||||
static CriticalSectionLock log_mutex;
|
||||
static FILE* logfile = NULL;
|
||||
static bool tried_to_open = false;
|
||||
va_list args;
|
||||
|
|
@ -18,15 +17,16 @@ void logf(char* fmt, ...) {
|
|||
#endif
|
||||
// don't reopen every time: slow as shit
|
||||
if (!tried_to_open) {
|
||||
const std::lock_guard<std::mutex> lock(log_mutex);
|
||||
log_mutex.lock();
|
||||
|
||||
if (!logfile) {
|
||||
fopen_s(&logfile, "ifs_hook.log", "w");
|
||||
}
|
||||
tried_to_open = true;
|
||||
log_mutex.unlock();
|
||||
}
|
||||
if (logfile) {
|
||||
const std::lock_guard<std::mutex> lock(log_mutex);
|
||||
log_mutex.lock();
|
||||
|
||||
va_start(args, fmt);
|
||||
vfprintf(logfile, fmt, args);
|
||||
|
|
@ -35,6 +35,8 @@ void logf(char* fmt, ...) {
|
|||
|
||||
if(config.developer_mode)
|
||||
fflush(logfile);
|
||||
|
||||
log_mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -81,6 +83,17 @@ void string_replace(std::string &str, const char* from, const char* to) {
|
|||
}
|
||||
}
|
||||
|
||||
bool string_replace_first(std::string& str, const char* from, const char* to) {
|
||||
auto pos = str.find(from);
|
||||
if (pos == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
str.replace(pos, strlen(from), to);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
wchar_t *str_widen(const char *src)
|
||||
{
|
||||
int nchars;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ void logf(char* fmt, ...);
|
|||
char* snprintf_auto(const char* fmt, ...);
|
||||
int string_ends_with(const char * str, const char * suffix);
|
||||
void string_replace(std::string &str, const char* from, const char* to);
|
||||
bool string_replace_first(std::string &str, const char* from, const char* to);
|
||||
wchar_t *str_widen(const char *src);
|
||||
void str_tolower_inline(char* str);
|
||||
void str_tolower_inline(std::string &str);
|
||||
|
|
|
|||
58
layeredfs/winxp_mutex.hpp
Normal file
58
layeredfs/winxp_mutex.hpp
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
// This class is a lightweight replacement for std::mutex on Windows platforms.
|
||||
// std::mutex does not work on Windows XP SP2 with the latest VC++ libraries,
|
||||
// because it utilizes the Concurrency Runtime that is only supported on Windows
|
||||
// XP SP3 and above.
|
||||
|
||||
// mon addition: avoid std::lock_guard. It uses thread local storage and is just, in general, pain to compile properly.
|
||||
// This sucks, because RAII is awesome.
|
||||
|
||||
class CriticalSectionLock {
|
||||
public:
|
||||
CriticalSectionLock() { InitializeCriticalSection(&critical_section_); }
|
||||
~CriticalSectionLock() { DeleteCriticalSection(&critical_section_); }
|
||||
void lock() { EnterCriticalSection(&critical_section_); }
|
||||
void unlock() { LeaveCriticalSection(&critical_section_); }
|
||||
|
||||
private:
|
||||
CRITICAL_SECTION critical_section_;
|
||||
};
|
||||
|
||||
/**
|
||||
Copyright 2008 Google Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Code generated by the Protocol Buffer compiler is owned by the owner
|
||||
of the input file used when generating it. This code is not
|
||||
standalone and requires a support library to be linked with it. This
|
||||
support library is itself covered by the above license.
|
||||
|
||||
**/
|
||||
Loading…
Reference in New Issue
Block a user