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

Use native file I/O in local and overlay drive #3765

Merged
merged 4 commits into from
Jun 14, 2024
Merged

Use native file I/O in local and overlay drive #3765

merged 4 commits into from
Jun 14, 2024

Conversation

weirddan455
Copy link
Collaborator

Description

This PR replaces the use of C library I/O (fopen() and friends) with native file I/O. Windows uses Win32 API calls and everyone else uses POSIX.

I was also able to remove some hacky ftell() + fseek() nonsense that should not be needed since there's no library buffering. The OS itself will still buffer but that should be fine. All we care about is that a write followed by a read will return the new data.

I have some more work on the file I/O planned to better handle timestamps (which will depend on native file I/O) but I thought it would be best to put that in a separate PR and get this in first.

Manual testing

Tested on Windows (both MSYS2/GCC and MSVC/Clang) and Linux. Crystal Caves and Mortal Kombat saves work which had been problematic on Windows in the past.

Other games with save state tested: Secret of Monkey Island 2, Quake, Doom, Space Quest 1

Checklist

Please tick the items as you have addressed them. Don't remove items; leave the ones that are not applicable unchecked.

I have:

  • followed the project's contributing guidelines and code of conduct.
  • performed a self-review of my code.
  • commented on the particularly hard-to-understand areas of my code.
  • split my work into well-defined, bisectable commits, and I named my commits well.
  • applied the appropriate labels (bug, enhancement, refactoring, documentation, etc.)
  • checked that all my commits can be built.
  • confirmed that my code does not cause performance regressions (e.g., by running the Quake benchmark).
  • added unit tests where applicable to prove the correctness of my code and to avoid future regressions.
  • made corresponding changes to the documentation or the website according to the documentation guidelines.
  • locally verified my website or documentation changes.

@weirddan455 weirddan455 added the plumbing Issues related to low-level support functions and classes label Jun 12, 2024
@weirddan455 weirddan455 self-assigned this Jun 12, 2024
include/dos_system.h Outdated Show resolved Hide resolved
include/fs_utils.h Outdated Show resolved Hide resolved
include/fs_utils.h Outdated Show resolved Hide resolved
include/fs_utils.h Outdated Show resolved Hide resolved
include/fs_utils.h Outdated Show resolved Hide resolved
include/fs_utils.h Outdated Show resolved Hide resolved
include/fs_utils.h Outdated Show resolved Hide resolved
include/fs_utils.h Outdated Show resolved Hide resolved
@shermp
Copy link
Collaborator

shermp commented Jun 13, 2024

Is there a case for making these file i/o wrappers more generic so that other parts of the code could use them later. I'm talking about seek, read, write etc.

Other code that could use this would be the disk image code, in which case large file support would definitely be appreciated.

@weirddan455
Copy link
Collaborator Author

Is there a case for making these file i/o wrappers more generic so that other parts of the code could use them later. I'm talking about seek, read, write etc.

Other code that could use this would be the disk image code, in which case large file support would definitely be appreciated.

They're already fairly generic and should be fine to use elsewhere. Some of the calls (especially create and open) may need additional flags depending on the use-case but I think we can cross that bridge when we come to it.

Maybe I should rename the functions to create_native_file read_native_file, etc. I'll bump the size types up to int64_t as @johnnovak suggested as well.

Copy link
Collaborator

@FeralChild64 FeralChild64 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks OK. I have no remarks.

So far tried some Windows 3.1 software, Colonization game. and MkS_Vir virus scanner, didn't find any problems/

Previously, this was left to the individual DOS_Drive classes to check.
Move this to common code and set the correct error.
This matches what FreeDOS does.
Also remove flushing with ftell() + fseek()
Should not be needed with native I/O
@weirddan455
Copy link
Collaborator Author

weirddan455 commented Jun 13, 2024

Thanks for testing @FeralChild64

I pushed changes addressing the comments above. Mostly re-naming things and fixing formatting. I also changed to int64_t everywhere in these native I/O functions. The Win32 code needed some changes to accommodate 64 bit. SetFilePointer (used in seek_native_file) does a weird thing where it splits into two 32-bit words and I added a loop to ReadFile() and WriteFile() very similar to what I did with POSIX except the values get clamped to 32-bit max.

They should be suitable for use where-ever else in the code they might be needed. I renamed them as I said above to open_native_file and such (removing the local_drive prefix I had before). I also made the fat attributes on create_native_file a std::optional as that one doesn't make sense if we want to create a normal file on the host.

src/dos/drive_local.cpp Outdated Show resolved Hide resolved
Copy link
Member

@johnnovak johnnovak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is solid step in the right direction @weirddan455 🎉 Looks very good now, left one last comment about testing Blackthorne if you have the capacity. Great work!

@weirddan455
Copy link
Collaborator Author

I'll let you take a look at my last commit if you like @johnnovak addressing the Blackthrone issue.

@weirddan455
Copy link
Collaborator Author

Added a LOG_WARNING if the file seek fails. I wasn't quite sure what to do in this case because apparently the real DOS interrupt never fails. The most likely case is a game trying to seek before the beginning of the file so I'm just setting the file position to 0.

Blackthorn never hits this case. Using unsigned integer lets it succeed. I wanted this warning to be visible to end users rather than a debug log because it seems to be rare and I want users to put this in a bug report if my assumption proves to be incorrect.

Copy link
Member

@johnnovak johnnovak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Outstanding work @weirddan455, I'm glad you've managed to remove the Blackthorne hack as well 🚀 I agree with your last note about logging a warning, that's the best we can do.

@johnnovak johnnovak added the DOS Issues related to DOS integration or DOS commands label Jun 14, 2024
This removes a hack needed by Blackthrone
See comments for in-depth explanation
@weirddan455 weirddan455 merged commit 39d8414 into main Jun 14, 2024
32 checks passed
@weirddan455 weirddan455 deleted the wd/files branch June 16, 2024 14:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
DOS Issues related to DOS integration or DOS commands plumbing Issues related to low-level support functions and classes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants