From 683204519c6903a2f17d34d48abbe7b6032a9bd1 Mon Sep 17 00:00:00 2001 From: Muzychenko Andrey <33288308+k4zmu2a@users.noreply.github.com> Date: Sat, 6 Nov 2021 19:22:56 +0300 Subject: [PATCH] Added UTF-8 path support on Windows. Ref issue #82. --- SpaceCadetPinball/GroupData.cpp | 2 +- SpaceCadetPinball/Sound.cpp | 2 +- SpaceCadetPinball/SpaceCadetPinball.cpp | 19 +++++++++++++++++++ SpaceCadetPinball/loader.cpp | 2 +- SpaceCadetPinball/midi.cpp | 9 +++++---- SpaceCadetPinball/partman.cpp | 2 +- SpaceCadetPinball/pch.h | 10 ++++++++++ SpaceCadetPinball/winmain.cpp | 2 +- 8 files changed, 39 insertions(+), 9 deletions(-) diff --git a/SpaceCadetPinball/GroupData.cpp b/SpaceCadetPinball/GroupData.cpp index ee46dea..dbffde3 100644 --- a/SpaceCadetPinball/GroupData.cpp +++ b/SpaceCadetPinball/GroupData.cpp @@ -297,7 +297,7 @@ void DatFile::Finalize() // PINBALL2.MID is an alternative font provided in 3DPB data // Scaled down because it is too large for top text box /*auto file = pinball::make_path_name("PINBALL2.MID"); - auto fileHandle = fopen(file.c_str(), "rb"); + auto fileHandle = fopenu(file.c_str(), "rb"); fseek(fileHandle, 0, SEEK_END); auto fileSize = static_cast(ftell(fileHandle)); auto rcData = reinterpret_cast(new uint8_t[fileSize]); diff --git a/SpaceCadetPinball/Sound.cpp b/SpaceCadetPinball/Sound.cpp index 4fa9336..082377e 100644 --- a/SpaceCadetPinball/Sound.cpp +++ b/SpaceCadetPinball/Sound.cpp @@ -57,7 +57,7 @@ void Sound::PlaySound(Mix_Chunk* wavePtr, int time) Mix_Chunk* Sound::LoadWaveFile(const std::string& lpName) { - auto wavFile = fopen(lpName.c_str(), "r"); + auto wavFile = fopenu(lpName.c_str(), "r"); if (!wavFile) return nullptr; fclose(wavFile); diff --git a/SpaceCadetPinball/SpaceCadetPinball.cpp b/SpaceCadetPinball/SpaceCadetPinball.cpp index e639ce8..aa08ec4 100644 --- a/SpaceCadetPinball/SpaceCadetPinball.cpp +++ b/SpaceCadetPinball/SpaceCadetPinball.cpp @@ -34,6 +34,25 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine { return MainActual(lpCmdLine); } + +// fopen to _wfopen adapter, for UTF-8 paths +FILE* fopenu(const char* path, const char* opt) +{ + wchar_t* wideArgs[2]{}; + for (auto& arg : wideArgs) + { + auto src = wideArgs[0] ? opt : path; + auto length = MultiByteToWideChar(CP_UTF8, 0, src, -1, nullptr, 0); + arg = new wchar_t[length]; + MultiByteToWideChar(CP_UTF8, 0, src, -1, arg, length); + } + + auto fileHandle = _wfopen(wideArgs[0], wideArgs[1]); + for (auto arg : wideArgs) + delete[] arg; + + return fileHandle; +} #endif // Run program: Ctrl + F5 or Debug > Start Without Debugging menu diff --git a/SpaceCadetPinball/loader.cpp b/SpaceCadetPinball/loader.cpp index 4b68880..60ffc0f 100644 --- a/SpaceCadetPinball/loader.cpp +++ b/SpaceCadetPinball/loader.cpp @@ -158,7 +158,7 @@ int loader::get_sound_id(int groupIndex) } auto filePath = pinball::make_path_name(fileName); - auto file = fopen(filePath.c_str(), "rb"); + auto file = fopenu(filePath.c_str(), "rb"); if (file) { fread(&wavHeader, 1, sizeof wavHeader, file); diff --git a/SpaceCadetPinball/midi.cpp b/SpaceCadetPinball/midi.cpp index a049a67..9adc940 100644 --- a/SpaceCadetPinball/midi.cpp +++ b/SpaceCadetPinball/midi.cpp @@ -101,11 +101,12 @@ Mix_Music* midi::load_track(std::string fileName) if (i == 0) { auto filePath = basePath + ".MID"; - auto fileHandle = fopen(filePath.c_str(), "rb"); + auto fileHandle = fopenu(filePath.c_str(), "rb"); if (fileHandle) { fclose(fileHandle); - audio = Mix_LoadMUS(filePath.c_str()); + auto rw = SDL_RWFromFile(filePath.c_str(), "rb"); + audio = Mix_LoadMUS_RW(rw, 1); } } else @@ -115,7 +116,7 @@ Mix_Music* midi::load_track(std::string fileName) { // Dump converted MIDI file /*auto filePath = basePath + ".midi"; - FILE* fileHandle = fopen(filePath.c_str(), "wb"); + FILE* fileHandle = fopenu(filePath.c_str(), "wb"); fwrite(midi->data(), 1, midi->size(), fileHandle); fclose(fileHandle);*/ @@ -164,7 +165,7 @@ bool midi::play_track(Mix_Music* midi) /// Vector that contains MIDI file std::vector* midi::MdsToMidi(std::string file) { - auto fileHandle = fopen(file.c_str(), "rb"); + auto fileHandle = fopenu(file.c_str(), "rb"); if (!fileHandle) return nullptr; diff --git a/SpaceCadetPinball/partman.cpp b/SpaceCadetPinball/partman.cpp index 5c89df9..16d811c 100644 --- a/SpaceCadetPinball/partman.cpp +++ b/SpaceCadetPinball/partman.cpp @@ -16,7 +16,7 @@ DatFile* partman::load_records(LPCSTR lpFileName, bool fullTiltMode) dat8BitBmpHeader bmpHeader{}; dat16BitBmpHeader zMapHeader{}; - auto fileHandle = fopen(lpFileName, "rb"); + auto fileHandle = fopenu(lpFileName, "rb"); if (fileHandle == nullptr) return nullptr; diff --git a/SpaceCadetPinball/pch.h b/SpaceCadetPinball/pch.h index 40e2849..582609b 100644 --- a/SpaceCadetPinball/pch.h +++ b/SpaceCadetPinball/pch.h @@ -83,4 +83,14 @@ int Sign(T val) return (T(0) < val) - (val < T(0)); } +// UTF-8 path adapter for fopen on Windows, implemented in SpaceCadetPinball.cpp +#ifdef _WIN32 +extern FILE* fopenu(const char* path, const char* opt); +#else +inline FILE* fopenu(const char* path, const char* opt) +{ + return fopen(path, opt); +} +#endif + #endif //PCH_H diff --git a/SpaceCadetPinball/winmain.cpp b/SpaceCadetPinball/winmain.cpp index 5e4fa9c..d77b0aa 100644 --- a/SpaceCadetPinball/winmain.cpp +++ b/SpaceCadetPinball/winmain.cpp @@ -82,7 +82,7 @@ int winmain::WinMain(LPCSTR lpCmdLine) { auto datFileName = datFileNames[i]; auto datFilePath = pinball::make_path_name(datFileName); - auto datFile = fopen(datFilePath.c_str(), "r"); + auto datFile = fopenu(datFilePath.c_str(), "r"); if (datFile) { fclose(datFile);