Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lmu2png: Make search of Chipset in lmu2png case-insensitive #85

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

Ghabry
Copy link
Member

@Ghabry Ghabry commented Apr 24, 2024

While testing the other PR I was annoyed that the test game cannot be converted because basis.png is lowercase. ^^

Using std::filesystem, our tools are only executed on recent systems. So should be fine for our needs.

@Ghabry
Copy link
Member Author

Ghabry commented Apr 24, 2024

lol so much about "should be fine". Build fails on Windows 😅 ...

Otherwise requires UTF-16 conversion and Windows doesn't need this search anyway.
@lumiscosity
Copy link
Contributor

lumiscosity commented Apr 24, 2024

i've been testing some filepath stuff on windows and return std::filesystem::exists(filename); is a better alternative to the current windows code, as it actually works with special characters in the filepath (at least japanese characters)

EDIT: this seems to only work when building under msys2 mingw...

@Ghabry
Copy link
Member Author

Ghabry commented May 3, 2024

Okay I finally checked this now on Windows:

The fs::path constructor accepts std::string but it is in the legacy codepage.

What fails to compile is std::string name_lc = entry.path().filename(); because this returns a wchar_t on Windows. To get a std::string one can use std::string name_lc = entry.path().filename().u8string(); at least until C++17. Afterwards it fails because this function is deprecated (they invented std::u8string in C++20).


So I can use most of the fs-API without frustration. It is just the conversion back to strings that is an issue.


Now about fs::exists(fpath). When I hardcode it to fs::exists("主人公1.png") it fails for me.

It starts working when adding this Manifest here:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
  <application>
    <windowsSettings>
      <activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>
    </windowsSettings>
  </application>
</assembly>

@scurest
Copy link
Contributor

scurest commented Jan 13, 2025

I was also looking for this. I adapted it to current master

Patch
diff --git a/lmu2png/src/utils.cpp b/lmu2png/src/utils.cpp
index 09fcac5..b39cb31 100644
--- a/lmu2png/src/utils.cpp
+++ b/lmu2png/src/utils.cpp
@@ -19,6 +19,7 @@
 #include <cstdlib>
 #include <iostream>
 #include <fstream>
+#include <filesystem>
 #include <string>
 #include <algorithm>
 #include <map>
@@ -30,6 +31,8 @@
 #include "utils.h"
 #include "chipset.h"
 
+namespace fs = std::filesystem;
+
 using CharsetCacheMap = std::map<std::string, BitmapPtr>;
 
 static std::vector<std::string> resource_dirs = {};
@@ -75,9 +78,31 @@ void CollectResourcePaths(std::string& main_path) {
 
 std::string FindResource(const std::string& folder, const std::string& base_name) {
 	for (const auto& dir : resource_dirs) {
-		for (const auto& ext : {".png", ".bmp", ".xyz"}) {
-			if (Exists(dir + "/" + folder + "/" + base_name + ext))
-				return dir + "/" + folder + "/" + base_name + ext;
+		fs::path dirp = fs::path(dir) / folder;
+
+		for (const auto& ext : {".png", ".xyz", ".bmp"}) {
+			fs::path p = dirp / fs::u8path(base_name + ext);
+			if (fs::exists(p))
+				return p.string();
+		}
+
+		// Case insensitive search
+		if (fs::is_directory(dirp)) {
+			std::string target_stem = lcf::ReaderUtil::Normalize(base_name);
+
+			for (auto const& entry : fs::directory_iterator(dirp)) {
+				fs::path p = entry.path();
+
+				std::string stem = lcf::ReaderUtil::Normalize(p.stem().u8string());
+				if (stem != target_stem)
+					continue;
+
+				std::string ext = lcf::ReaderUtil::Normalize(p.extension().string());
+				if (!(ext == ".png" || ext == ".xyz" || ext == ".bmp"))
+					continue;
+
+				return p.string();
+			}
 		}
 	}
 

Tested on Linux. This will also scan the dir at most once per FindResource call, instead of at most three times (one per .png/.xyz/.bmp).

I believe it will work on Windows too, but I haven't tested it. Conversion from a fs::path back to a narrow char std::string just needs p.string(). It's probably not that good of an idea to do on Windows though.

Unicode is really completely unrelated to this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

4 participants