Skip to content

Commit af7c677

Browse files
committed
Fix merge + remove PAK check
1 parent d08a96e commit af7c677

File tree

4 files changed

+11
-236
lines changed

4 files changed

+11
-236
lines changed

src/Mods.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Mods::Mods() {
3636
m_mods.emplace_back(LooseFileLoader::get());
3737

3838
#if defined(MHWILDS)
39-
m_mods.emplace_back(FaultyFileDetector::get_existing_instance());
39+
m_mods.emplace_back(FaultyFileDetector::get());
4040
#endif
4141

4242
m_mods.emplace_back(VR::get());

src/REFramework.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ extern "C" {
3131
#include "utility/Thread.hpp"
3232

3333
#include "Mods.hpp"
34+
#include "mods/FaultyFileDetector.hpp"
3435
#include "mods/LooseFileLoader.hpp"
3536
#include "mods/PluginLoader.hpp"
3637
#include "mods/VR.hpp"
@@ -560,11 +561,18 @@ REFramework::REFramework(HMODULE reframework_module)
560561
auto& loader = LooseFileLoader::get(); // Initialize this really early
561562
auto &integrity_bypass = IntegrityCheckBypass::get_shared_instance();
562563

564+
#if defined(MHWILDS)
565+
auto& faulty_file_detector = FaultyFileDetector::get();
566+
#endif
567+
563568
const auto config_path = get_persistent_dir(REFrameworkConfig::REFRAMEWORK_CONFIG_NAME.data()).string();
564569
if (fs::exists(utility::widen(config_path))) {
565570
utility::Config cfg{ config_path };
566571
loader->on_config_load(cfg);
567572
integrity_bypass->on_config_load(cfg);
573+
#if defined(MHWILDS)
574+
faulty_file_detector->on_config_load(cfg);
575+
#endif
568576
}
569577

570578
if (loader->is_enabled()) {

src/mods/FaultyFileDetector.cpp

Lines changed: 1 addition & 233 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ const char *faulty_reason_to_string(FaultyFileDetector::FaultyReason reason) {
3131
return "Missing file";
3232
case FaultyFileDetector::FaultyReason::Invalid:
3333
return "Invalid file";
34-
case FaultyFileDetector::FaultyReason::ShouldBeEncrypted:
35-
return "PAK should be encrypted";
3634
default:
3735
return "Unknown reason";
3836
}
@@ -532,7 +530,6 @@ void FaultyFileDetector::on_draw_ui() {
532530
{FaultyReason::Unknown, {"Unknown", ImVec4(0.8f, 0.8f, 0.8f, 1.0f)}},
533531
{FaultyReason::MissingFile, {"Missing File", ImVec4(1.0f, 1.0f, 0.0f, 1.0f)}},
534532
{FaultyReason::Invalid, {"Invalid File", ImVec4(1.0f, 0.5f, 0.0f, 1.0f)}},
535-
{FaultyReason::ShouldBeEncrypted, {"Should Be Encrypted", ImVec4(1.0f, 0.0f, 0.0f, 1.0f)}},
536533
};
537534

538535
if (ImGui::TreeNode("Show recent##ShowRecentFaultyFiles")) {
@@ -575,243 +572,14 @@ void FaultyFileDetector::on_draw_ui() {
575572
}
576573
}
577574

578-
void FaultyFileDetector::on_pak_load_result(bool success, std::wstring_view pak_name) {
579-
FaultyBufferEntry faulty_entry{};
580-
if (success) {
581-
faulty_entry = detect_if_success_pak_still_suspicious(pak_name);
582-
} else {
583-
faulty_entry = determine_pak_faulty_tier(pak_name);
584-
}
585-
if (faulty_entry.tier != FaultyTier::None) {
586-
if (s_instance == nullptr) {
587-
faulty_entry.filename = std::wstring{pak_name};
588-
s_buffered_faulties.push_back(faulty_entry);
589-
} else {
590-
s_instance->try_add_to_faulty_list(pak_name, faulty_entry.tier, faulty_entry.reason);
591-
}
592-
}
593-
}
594-
595-
std::optional<int> FaultyFileDetector::extract_patch_version_from_pak_name(std::wstring_view pak_name) {
596-
auto pak_name_copy = std::wstring{pak_name};
597-
std::wsmatch match;
598-
599-
if (std::regex_match(pak_name_copy, match, s_extract_patch_version_regex)) {
600-
if (match.size() >= 3) {
601-
try {
602-
return std::stoi(match[2].str());
603-
} catch (const std::exception& e) {
604-
spdlog::warn("[FaultyFileDetector]: Failed to parse patch version from PAK name: {}", utility::narrow(pak_name));
605-
}
606-
}
607-
}
608-
609-
return std::nullopt;
610-
}
611-
612-
bool FaultyFileDetector::check_is_stock_patch_pak(std::wstring_view pak_name) {
613-
cache_patch_version();
614-
615-
auto version_opt = extract_patch_version_from_pak_name(pak_name);
616-
if (version_opt.has_value()) {
617-
int pak_version = version_opt.value();
618-
if (s_patch_version_cached && pak_version <= s_patch_version) {
619-
return true;
620-
}
621-
}
622-
return false;
623-
}
624-
625-
FaultyFileDetector::FaultyBufferEntry FaultyFileDetector::detect_if_success_pak_still_suspicious(std::wstring_view pak_name) {
626-
struct PAKHeaderSimple {
627-
char signature[4];
628-
uint8_t major_version;
629-
uint8_t minor_version;
630-
uint8_t flags;
631-
};
632-
633-
enum PAKFlags : uint8_t {
634-
Encrypted = 1 << 3,
635-
};
636-
637-
const char *signature = "KPKA";
638-
639-
auto game = utility::get_executable();
640-
auto game_path_opt = utility::get_module_path(game);
641-
642-
FaultyFileDetector::FaultyBufferEntry result{};
643-
644-
if (game_path_opt.has_value()) {
645-
auto game_path = std::filesystem::path(game_path_opt.value()).parent_path();
646-
auto pak_path = game_path / pak_name;
647-
648-
if (!std::filesystem::exists(pak_path)) {
649-
result.tier = FaultyFileDetector::FaultyTier::Severe;
650-
result.reason = FaultyFileDetector::FaultyReason::MissingFile;
651-
652-
return result;
653-
} else {
654-
// Read PAK header
655-
std::ifstream pak_file_stream{pak_path, std::ios::binary};
656-
if (!pak_file_stream.is_open()) {
657-
spdlog::warn("[FaultyFileDetector]: Failed to open PAK file for reading: {}", utility::narrow(pak_path.wstring()));
658-
result.tier = FaultyFileDetector::FaultyTier::Warning;
659-
result.reason = FaultyFileDetector::FaultyReason::MissingFile;
660-
661-
return result;
662-
} else {
663-
PAKHeaderSimple header{};
664-
pak_file_stream.read(reinterpret_cast<char*>(&header), sizeof(PAKHeaderSimple));
665-
666-
if (!pak_file_stream) {
667-
spdlog::warn("[FaultyFileDetector]: Failed to read PAK header from file: {}", utility::narrow(pak_path.wstring()));
668-
result.tier = FaultyFileDetector::FaultyTier::Warning;
669-
result.reason = FaultyFileDetector::FaultyReason::MissingFile;
670-
return result;
671-
}
672-
673-
if (std::memcmp(header.signature, signature, 4) != 0) {
674-
spdlog::warn("[FaultyFileDetector]: Invalid PAK signature in file: {}", utility::narrow(pak_path.wstring()));
675-
result.tier = FaultyFileDetector::FaultyTier::Severe;
676-
result.reason = FaultyFileDetector::FaultyReason::Invalid;
677-
return result;
678-
}
679-
680-
if (pak_name.contains(L"patch")) {
681-
bool is_stock_patch = check_is_stock_patch_pak(pak_name);
682-
if (is_stock_patch) {
683-
// Stock patch PAK should be encrypted (put it as warning for now)
684-
if (!(header.flags & PAKFlags::Encrypted)) {
685-
spdlog::warn("[FaultyFileDetector]: Stock patch PAK is not encrypted: {}", utility::narrow(pak_path.wstring()));
686-
result.tier = FaultyFileDetector::FaultyTier::Warning;
687-
result.reason = FaultyFileDetector::FaultyReason::ShouldBeEncrypted;
688-
return result;
689-
}
690-
}
691-
}
692-
693-
return result;
694-
}
695-
}
696-
} else {
697-
return result;
698-
}
699-
}
700-
701-
FaultyFileDetector::FaultyBufferEntry FaultyFileDetector::determine_pak_faulty_tier(std::wstring_view pak_name) {
702-
FaultyFileDetector::FaultyBufferEntry result{};
703-
704-
if (pak_name.contains(L"dlc")) {
705-
result.tier = FaultyTier::Severe;
706-
result.reason = FaultyReason::Invalid;
707-
708-
return result;
709-
}
710-
711-
auto patch_position_in_name = pak_name.find(L"patch");
712-
713-
if (patch_position_in_name != std::wstring_view::npos) {
714-
cache_patch_version();
715-
716-
auto game_module = utility::get_executable();
717-
auto game_path_opt = utility::get_module_path(game_module);
718-
719-
if (game_path_opt.has_value()) {
720-
auto game_path = std::filesystem::path(game_path_opt.value()).parent_path();
721-
auto filename_before_patch = pak_name.substr(0, std::max<int>(0, (int)patch_position_in_name - 1));
722-
723-
auto patch_target_pak = game_path / filename_before_patch;
724-
if (!std::filesystem::exists(patch_target_pak)) {
725-
// Target patch PAK does not exist, false positive
726-
return result;
727-
} else {
728-
// Target patch PAK exists, check if its existence is necessary first
729-
bool is_stock_patch_pak = check_is_stock_patch_pak(pak_name);
730-
731-
if (is_stock_patch_pak) {
732-
result.tier = FaultyTier::Severe;
733-
734-
if (std::filesystem::exists(game_path / pak_name)) {
735-
result.reason = FaultyReason::Invalid;
736-
} else {
737-
result.reason = FaultyReason::MissingFile;
738-
}
739-
740-
return result;
741-
} else {
742-
// The PAK is probably in modded PAK range, if it does not exist then its fine
743-
auto pak_path = game_path / pak_name;
744-
if (std::filesystem::exists(pak_path)) {
745-
result.tier = FaultyTier::Severe;
746-
result.reason = FaultyReason::Invalid;
747-
748-
return result;
749-
} else {
750-
return result;
751-
}
752-
}
753-
}
754-
}
755-
} else {
756-
result.tier = FaultyTier::Severe;
757-
result.reason = FaultyReason::Invalid;
758-
}
759-
760-
return result;
761-
}
762-
763-
void FaultyFileDetector::cache_patch_version() {
764-
if (s_patch_version_cached) {
765-
return;
766-
}
767-
768-
const wchar_t *patch_version_prefix = L"/Environment/Package/PatchVersion:";
769-
770-
auto argument_count_method = sdk::find_method_definition("via.Application", "getArgumentCount");
771-
if (argument_count_method == nullptr) {
772-
spdlog::warn("[FaultyFileDetector]: Failed to find via.Application::getArgumentCount method for patch version detection");
773-
return;
774-
}
775-
776-
int argument_count = argument_count_method->call<int>();
777-
for (int i = 0; i < argument_count; i++) {
778-
auto argument_value_method = sdk::find_method_definition("via.Application", "getArgument");
779-
if (argument_value_method == nullptr) {
780-
spdlog::warn("[FaultyFileDetector]: Failed to find via.Application::getArgument method for patch version detection");
781-
return;
782-
}
783-
784-
auto arg_value_obj = argument_value_method->call<SystemString*>(sdk::get_thread_context(), i);
785-
if (arg_value_obj != nullptr) {
786-
auto arg_str = utility::re_string::get_view(arg_value_obj);
787-
spdlog::info("[FaultyFileDetector]: Detected argument: {}", utility::narrow(arg_str));
788-
if (arg_str.starts_with(patch_version_prefix)) {
789-
auto version_str = arg_str.substr(wcslen(patch_version_prefix));
790-
try {
791-
s_patch_version = std::stoi(utility::narrow(version_str));
792-
s_patch_version_cached = true;
793-
794-
spdlog::info("[FaultyFileDetector]: Detected patch version: {}", s_patch_version);
795-
} catch (const std::exception& e) {
796-
spdlog::warn("[FaultyFileDetector]: Failed to parse patch version from argument: {}", utility::narrow(arg_str));
797-
}
798-
break;
799-
}
800-
} else {
801-
spdlog::warn("[FaultyFileDetector]: Argument value at index {} is null", i);
802-
}
803-
}
804-
}
805-
806575
void FaultyFileDetector::early_init() {
807576
if (g_faulty_detector_instance == nullptr) {
808577
g_faulty_detector_instance = std::make_unique<FaultyFileDetector>();
809578
}
810579

811-
IntegrityCheckBypass::add_pak_load_result_listener(&FaultyFileDetector::on_pak_load_result);
812580
g_faulty_detector_instance->initialize_impl();
813581
}
814582

815-
std::shared_ptr<FaultyFileDetector>& FaultyFileDetector::get_existing_instance() {
583+
std::shared_ptr<FaultyFileDetector>& FaultyFileDetector::get() {
816584
return g_faulty_detector_instance;
817585
}

src/mods/FaultyFileDetector.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ class FaultyFileDetector : public Mod {
2525
Unknown = 0,
2626
MissingFile = 1,
2727
Invalid = 2,
28-
ShouldBeEncrypted = 3,
2928
};
3029

3130
struct FaultyBufferEntry {
@@ -44,7 +43,7 @@ class FaultyFileDetector : public Mod {
4443
void on_draw_ui() override;
4544

4645
static void early_init();
47-
static std::shared_ptr<FaultyFileDetector>& get_existing_instance();
46+
static std::shared_ptr<FaultyFileDetector>& get();
4847

4948
private:
5049
static sdk::Resource* create_resource_hook_wrapper(sdk::ResourceManager *resource_manager, void* type_info, wchar_t* name);

0 commit comments

Comments
 (0)