Skip to content

Improve cross-platform (particularly Linux) support with case-insensitive path handling among other things#145

Open
xormatrix wants to merge 7 commits intoVoljega:masterfrom
xormatrix:master
Open

Improve cross-platform (particularly Linux) support with case-insensitive path handling among other things#145
xormatrix wants to merge 7 commits intoVoljega:masterfrom
xormatrix:master

Conversation

@xormatrix
Copy link

@xormatrix xormatrix commented Aug 2, 2025

Improve cross-platform compatibility and case-sensitive filesystem support. I've added two functions for resolving paths given case-insensitive paths (getActualFilesystemFilename() and getActualFilesystemPath()). These are necessary to deal with the case-insensitive paths in batch and .cue files.

I've also changed the encoding used in gamegenerator.py from mbcs (a Windows-only encoding) to cp1252. This fixes rezipping games for dosbox-pure in Linux.

Lastly, I made some small changes and improved the code readability for the sections I changed, for the sake of safety and clarity.

There may still be some changes necessary, I've already done some testing but it's difficult to be sure, someone more experienced with the codebase must judge that.

mbcs is a Windows-only encoding. Change encoding to
cp1252 for better cross-platform support. Fixes Voljega#138.
* getActualFilesystemFilename(): Get the actual filename that
  exists in the filesystem from a case-insensitive filename.
* getActualFilesystemPath(): Recursive version
  of getActualFilesystemFilename().

These functions are necessary for better case-sensitive filesystem
support with regards to how batch files and .cue specify paths in
a case-insensitive way. We need a way to resolve these paths
regardless of case no matter the filesystem or operating system.

Extra: Improved implemenentation of localOSPath()
       with the use of PurePath and PureWindowsPath.
Use the new case-insensitive path functions
(util.getActualFilesystemPath() and the like) to properly resolve
paths from batch files and .cue files. Improve code readability
while we're at it and make some additional small changes for the
sake of safety and clarity.
@xormatrix xormatrix changed the title commandhandler.py: case-insensitive path resolution Improve cross-platform (particularly Linux) support with case-insensitive path handling among other things Aug 2, 2025
@Voljega
Copy link
Owner

Voljega commented Aug 3, 2025

Hello,
Thank you for the PR.

I'm ill at the moment so I'm in no mental shape to review this, but I'll get back to you as soon as I can.

Add an option 'cached_listdir' to getActualFilesystemFilename().
This option specifies a list of filenames to search through
(e.g. from os.listdir()).
This is useful if you need to use getActualFilesystemFilename()
multiple times in a single directory, using 'cached_listdir' then
avoids excessive filesystem access operations.
Handle any discrepancies between the .csv collection cache
(which maps the full game name -> game directory name)
and the actual directory names in the collection config directory.
Should fix Voljega#119, though further testing may be required.

EXAMPLE:

The eXoDOSv6.csv collection cache maps the
full game name to the game directory name:
  * "Commander Keen - Keen Dreams (1993)" -> "CKeenDr"
But what if in a new release of eXoDOS, the game directory name were
changed to "ckeendr"? On a case-sensitive filesystem, the code looks for
"CKeenDr" (from the collection cache) and doesn't find it, but on a
case-insensitive filesystem there would be no issues (such as NTFS).
To avoid any issues, resolve the game directory from the cache to its
actual case-corrected filesystem name (in this case, "ckeendr")
before continuing.
During game directory name resolution, remove any found game
directories such that searching gets progressively faster.
Tested on my computer, this speeds up the process by ~18x for eXoDOS.
@v4u6h4n
Copy link

v4u6h4n commented Dec 14, 2025

@xormatrix

Ran into this when trying out your changes to get around the mbcs issue. I don't know my way around python enough to know what I'm looking at...

eXoConverter 0.9.6-beta
Script path : /media/storage/games/collections/exodos/ExoDOSConverter
Traceback (most recent call last):
File "/media/storage/games/collections/exodos/ExoDOSConverter/main.py", line 15, in
gui.draw()
~~~~~~~~^^
File "/media/storage/games/collections/exodos/ExoDOSConverter/exogui.py", line 115, in draw
self.drawMainframe()
~~~~~~~~~~~~~~~~~~~~~~^^
File "/media/storage/games/collections/exodos/ExoDOSConverter/exogui.py", line 132, in drawMainframe
self.drawPathsFrame()
~~~~~~~~~~~~~~~~~~~~~~~^^
File "/media/storage/games/collections/exodos/ExoDOSConverter/exogui.py", line 169, in drawPathsFrame
self.fullnameToGameDir = util.fullnameToGameDir(self.guiVars['collectionDir'].get(), self.scriptDir, self.configuration['collectionVersion'], self.logger)
~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/media/storage/games/collections/exodos/ExoDOSConverter/util.py", line 427, in fullnameToGameDir
gamedirs_actual = os.listdir(collectionGamesConfDir)
FileNotFoundError: [Errno 2] No such file or directory: 'H:\eXo\eXoWin3x/eXo/eXoWin3x/!win3x'

@xormatrix
Copy link
Author

@v4u6h4n Sorry for the late response. I'd assume you've already figured out the issue but just in case I'll post the solution here. collectionGamesConfDir refers to the "Collection folder" in the GUI. It's the first path in the GUI (right at the top) which you need to set. H:\eXo\eXoWin3x is the default path if you haven't changed it yourself.

But yes, the errors are a bit cryptic I agree.

@v4u6h4n
Copy link

v4u6h4n commented Jan 2, 2026

Hey @xormatrix :-)

Thanks for the reply, the error actually occurs before the GUI spawns, so I can't change the value. I messed around with (and reverted) conf/conf-exo.conf, but that didn't fix anything. The equivalent of poking the code with a stick I suppose, so not a surprise.

I did manage to just switch the encoding over to cp1252 in gamegenerator.py to fix issues I was running into though, so there is some progress there at least.

@xormatrix
Copy link
Author

@v4u6h4n Alright it's fixed now :) It was a simple fix.

Resolving the actual game directory names (with correct casing) from the collection folder is only possible if the collection folder, y'know, actually exists. Otherwise Python raises a FileNotFound error. The default is H:\eXo\eXoWin3x which of course doesn't exist on linux, so it's no surprise this happened.

Now the code first checks if the collection folder exists, if not it send an error message asking the user to select an existing folder and also returns an empty game list.

@v4u6h4n
Copy link

v4u6h4n commented Jan 6, 2026

Hello again. Thanks for the help! :-) that did the trick; I can actually get it outputting something playable now. I am getting a lot of imagemount errors in dos when it first boots up, but the game does run afterwards. So I'm not sure what's going on there, I'll have a play around and see if I can get different results with different conversion types.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

mbcs is a Windows only encoding Case sensitivity errors in eXoDOS v6

3 participants