Commit Graph

877 Commits

Author SHA1 Message Date
Jason Yundt
5a199429b6 Set activeCodePage to UTF-8
Consider this program:

  #include <cstdio>

  int main(void) {
    const char *filename = u8"ディセント3.txt";
    auto fp = std::fopen(filename, "r");
    if (fp) {
      std::fclose(fp);
      return 0;
    } else {
      return 1;
    };
  }

If a file named ディセント3.txt exists, then will that program
successfully open it? The answer is: it depends.

filename is going to point to these bytes:

  Raw bytes: e3 83 87 e3 82 a3 e3 82 bb e3 83 b3 e3 83 88 33 2e 74 78 74 00
  Characters: ディセント3.txt␀

Internally, Windows uses UTF-16. When you call fopen(), Windows will
convert the filename parameter into UTF-16 [1]. If the program is run
with a UTF-8 Windows code page, then the above bytes will be correctly
interpreted as UTF-8 when being converted into UTF-16 [2]. The final
UTF-16 string will be this*:

  Raw bytes: ff fe c7 30 a3 30 bb 30 f3 30 c8 30 33 00 2e 00 74 00 78 00 74 00
  Characters: ディセント3.txt

On the other hand, if the program is run with code page 932, then the
original bytes will be incorrectly interpreted as code page 932 when
being converted into UTF-16. The final UTF-16 string will be this*:

  Raw bytes: ff fe 5d 7e fd ff 67 7e 63 ff 67 7e 7b ff 5d 7e 73 ff 5d 7e fd ff 33 00 2e 00 74 00 78 00 74 00
  Characters: 繝�繧」繧サ繝ウ繝�3.txt

In other words, if that program gets compiled on Windows with a UTF-8
execution character set, then it needs to be run with a UTF-8 Windows
code page. Otherwise, mojibake might happen.

*Unlike the first string, this one does not have a null terminator. This
is because the Windows kernel doesn’t use null terminated strings for
paths [3][4].

---

Before this commit, Descent 3 would pass UTF-8 to fopen(), even if
Descent 3 is run with a non-UTF-8 Windows code page [5]. This commit
makes sure that Descent 3 gets run with a UTF-8 Windows code page.

The Windows code page isn’t just used by fopen(). It also gets used by
many other functions in the Windows API [6]. I don’t know if Descent 3
uses any of those other functions, but if it does, then this commit will
also help make sure that those functions receive strings with the
correct character encoding. Descent 3 uses UTF-8 for strings by default
[7]. Making sure that Descent 3 uses UTF-8 everywhere will make
encoding-related mistakes less likely in the future.

Fixes #483.

[1]: <https://stackoverflow.com/a/7950569/7593853>
[2]: <https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/fopen-wfopen?view=msvc-170#remarks>
[3]: <https://stackoverflow.com/a/52372115/7593853>
[4]: <https://googleprojectzero.blogspot.com/2016/02/the-definitive-guide-on-win32-to-nt.html>
[5]: <https://github.com/DescentDevelopers/Descent3/pull/475#discussion_r1664888080>
[6]: <https://learn.microsoft.com/en-us/windows/apps/design/globalizing/use-utf8-code-page#-a-vs--w-apis>
[7]: adf58eca (Explicitly declare execution character set, 2024-07-07)
2024-07-17 10:25:40 -04:00
Jason Yundt
adf58eca81 Explicitly declare execution character set
Consider this program:

  #include <cstdio>

  int main(void) {
    const char *example_string = "ディセント3";
    for (size_t i = 0; example_string[i] != '\0'; ++i) {
      printf("%02hhx ", example_string[i]);
    }
    puts("");

    return 0;
  }

What will that program output? The answer is: it depends. If that
program is compiled with a UTF-8 execution character set, then it will
print this:

  e3 83 87 e3 82 a3 e3 82 bb e3 83 b3 e3 83 88 33

If that program is compiled with a Shift JIS execution character set,
then it will print this:

  83 66 83 42 83 5a 83 93 83 67 33

This is especially a problem when using MSVC. MSVC doesn’t necessarily
default to using UTF-8 as a program’s execution character set [1].

---

Before this change, Descent 3 would use whatever the default execution
character set was. This commit ensures that the execution character set
is UTF-8 as long as Descent 3 gets compiled with MSVC, GCC or Clang. If
Descent 3 is compiled with a different compiler, then a different
execution character set might get used, but as far as I know, we only
support MSVC, GCC and Clang.

I’m not sure whether or not this change has any noticeable effects. If
using different execution character sets do have noticeable effects,
then this change will hopefully ensure that those effects are the same
for everyone.

[1]: <https://learn.microsoft.com/en-us/answers/questions/1805730/what-is-msvc-s-default-execution-character-set>
2024-07-17 10:13:34 -04:00
Jason Yundt
dd757e9034 Explicitly declare that source files are UTF-8
Before this change, there was a chance that a text editor or compiler
would use the wrong character encoding. For text editors, this commit
adds “charset = utf-8” to .editorconfig. That will cause editors that
support EditorConfig files [1] to automatically use UTF-8 when reading
and writing files. For compilers, this commit adds compiler options that
guarantee that compilers will decode source code files using UTF-8. The
compiler options are known to work on MSVC, GCC and Clang. If we ever
want to support additional compilers, then we might have to edit the if
statement that this commit adds.

This commit does not eliminate the chance that a wrong character
encoding will be used. Someone could always use a text editor that
doesn’t support EditorConfig files or a compiler that doesn’t support
the compiler options that we use. This commit does, however, make an
encoding mismatch much less likely.

[1]: <https://editorconfig.org/#pre-installed>
2024-07-17 10:12:09 -04:00
Louis Gombert
308d82e276
Merge pull request #486 from winterheart/fix-cfile-update
Additional fixes to cfile DLL exports
2024-07-14 15:18:45 +00:00
Azamat H. Hackimov
1ef1144a46
Merge pull request #493 from tophyr/pr/remove-loki
Remove loki_utils
2024-07-13 11:44:06 +03:00
Chris Sarbora
822a411433
Remove loki_utils
Inline the only usage of `loki_getprefpath()`, and use `Base_directory` (controlled by `-setdir`) instead of `loki_getdatapath()`.

Inline or eliminate some other code that became empty/unused with loki removal.
2024-07-13 03:23:10 -05:00
Louis Gombert
87f6ef009f
Merge pull request #488 from pzychotic/fix-no-intro-crash
Fix crash with -nointro
2024-07-10 19:32:26 +00:00
Thomas Roß
bdfb20af21 [Movie] Fixed a crash when -no-intro is used on the command line. 2024-07-10 20:48:17 +02:00
Louis Gombert
3c66b13200
Merge pull request #289 from winterheart/mve
Implementing own MVE library
2024-07-09 20:56:56 +00:00
Azamat H. Hackimov
5a4e1533a6 Fix playback case-insensitive intros 2024-07-09 09:47:11 +03:00
Azamat H. Hackimov
ae279d1211 Documenting ISoundDevice classes 2024-07-09 03:42:52 +03:00
Azamat H. Hackimov
32df86203a Cleanup d3movie.cpp
Remove unused variables, minor fixes.
2024-07-09 03:42:52 +03:00
Azamat H. Hackimov
c6eb9a8908 MVE: rename lnx_sound to sdl_sound
Now this is cross-platform playback.
2024-07-09 03:42:52 +03:00
Azamat H. Hackimov
4f0e0f87a5 Cleanup MVE library
Remove old implementation, cleanup unused code.
2024-07-09 03:40:49 +03:00
Azamat H. Hackimov
def4737f53 Cleanup cinematics.cpp
Don't stop main sound subsystem as it now not interfere MVE playback. Removed unused debug variable.
2024-07-09 03:40:49 +03:00
Azamat H. Hackimov
9672475f70 Update MVE playback on Windows
There only one problem still persist on playback - slow filling sound buffer from std::deque on MSVC Debug mode due extremely slow performance of STL containers on that mode. On Release and RelWithDebInfo playback is fine.
2024-07-09 03:40:49 +03:00
Azamat H. Hackimov
8fd119bd3d MVE: Make timer code crossplatform 2024-07-09 03:40:49 +03:00
Azamat H. Hackimov
a39ccfc3ca MVE: Implementing class for sound playback
Implemented abstraction layer and SDL backend.
2024-07-09 03:40:49 +03:00
Azamat H. Hackimov
2f288f6dc9 MVE: use deque for FIFO buffer
Replacing circular ring implementation with queue that keeps decoded data between SDL audio callbacks.
2024-07-09 03:40:49 +03:00
Azamat H. Hackimov
8d56e1c1ff MVE: Migrate to SDL2 functions
Replaced SDL 1.2 legacy calls to SDL2 equivalents.
Changed spec.size to fixed value 4096 as values obtained from file can produce sound stuttering.
2024-07-09 03:40:49 +03:00
Azamat H. Hackimov
96c240a4c0 MVE: Add support for big-endian systems 2024-07-09 03:40:49 +03:00
Azamat H. Hackimov
afd7c1a636 MVE: Initial sound support
Sound supported by SDL backend.
2024-07-09 03:40:49 +03:00
Azamat H. Hackimov
a8784ee524 MVE: Implementing frame playing (main menu)
Reorganized MVE to use own MVESTREAM pointer for each opened MVE file.
2024-07-09 03:40:49 +03:00
Azamat H. Hackimov
99ec2e3a5e MVE: Refactoring code
Merge libmve.h into mvelib.h
2024-07-09 03:40:49 +03:00
Azamat H. Hackimov
b94458f561 MVE: Switch to D2X implementation (first run)
Adapting movie and mve interfaces each other.
Converted open() to fopen() et al. calls.
movie expected image as RGB565 from old mve, but now it's RGB555, so there no need additional conversion. Fixed hicolor related conversion of width in movie's callbacks. Headers cleanup in both subsystems.

Sound and frame callbacks are still unavailable.
2024-07-09 03:40:49 +03:00
Azamat H. Hackimov
a5b86bd0fb MVE: convert libmve files to C++ 2024-07-09 03:40:49 +03:00
Azamat H. Hackimov
ce74c43b44 MVE: add copyright headers, clang-format 2024-07-09 03:40:49 +03:00
Azamat H. Hackimov
ef60434f72 Add D2X implementation of MVE
Added D2X implementation licensed under GPLv3 terms.
Cut from c030c4531a
2024-07-09 03:40:49 +03:00
Azamat H. Hackimov
1ae023a13b Enumerate all DLL functions manually
Enumerate DLL functions to ease tying functions in main and DLL sides in code.
2024-07-09 02:08:25 +03:00
Azamat H. Hackimov
4279373307 Additional fix for cfile regressions
On starting multiplayer missions OpenCFILE() loses filename value. Change OpenCFILE() signature to use std::fs::path too.
2024-07-09 01:19:58 +03:00
Louis Gombert
d85aa5c158
Merge pull request #484 from winterheart/network-cfile
Fix runtime error on creating multiplayer game
2024-07-08 08:31:41 +00:00
Azamat H. Hackimov
45aa389f68 Move content from dmfcdllinit.h
Simplify code.
2024-07-08 11:15:18 +03:00
Azamat H. Hackimov
0bae89dd05 Fix runtime error on creating multiplayer game
Update dll typedefs to reflect cfile API changes.
2024-07-08 11:15:18 +03:00
Louis Gombert
de75a80ae7
Merge pull request #475 from winterheart/cfile-std-filesystem
cfile / ddio: use most of functions to std::filesystem::path
2024-07-06 23:25:12 +00:00
Azamat H. Hackimov
2fce643ae8 Use case-insensitive search for cf_OpenLibrary() on all platforms 2024-07-05 01:50:57 +03:00
Azamat H. Hackimov
7a1f08e811 Fix unittests on macOS
Surprisingly on macOS FS is case-insensitive.
2024-07-05 01:50:57 +03:00
Azamat H. Hackimov
b3affdb105 Use new cf_FindRealFileNameCaseInsensitive() function in code
A little speed-up for our slowpoke.
2024-07-05 01:50:57 +03:00
Azamat H. Hackimov
1a3c012228 Refactor cf_FindRealFileNameCaseInsensitive() function
Implementing cf_FindRealFileNameCaseInsensitive_new() based on std::fs::directory_iterator, which runs faster and more reliable.

cf_FindRealFileNameCaseInsensitive_new() works exactly as cf_FindRealFileNameCaseInsensitive().

Benchmark on Release build:

```
-------------------------------------------------------------------
Benchmark                         Time             CPU   Iterations
-------------------------------------------------------------------
cfile_no_exist_old            11607 ns        11399 ns        63035
cfile_no_exist_new             9302 ns         9196 ns        70041
cfile_exist_relative_old       2701 ns         2480 ns       282695
cfile_exist_relative_new        867 ns          866 ns       798478
cfile_exist_absolute_old       3415 ns         3167 ns       228323
cfile_exist_absolute_new       1182 ns         1181 ns       574782
```
2024-07-05 01:50:57 +03:00
Azamat H. Hackimov
f44f6a4bbd CFILE: change signature of cf_FindRealFileNameCaseInsenstive()
Moved directory parameter to 3rd position and make it optional.
2024-07-05 01:50:57 +03:00
Azamat H. Hackimov
c287a2df48 Fix compilation of Descent3Editor
Convert some of the paths to use std::fs::path.
2024-07-05 01:50:57 +03:00
Azamat H. Hackimov
41ec941b50 Convert bm_SaveFileBitmap() and SaveVClip() to std::fs::path 2024-07-05 01:50:57 +03:00
Azamat H. Hackimov
5222bb28f3 Update cinematics API to use std::fs::path 2024-07-05 01:50:57 +03:00
Azamat H. Hackimov
65520373e6 CFILE: Remove duplicated code in open_file_in_directory()
Refactoring platform-dependent parts of code into common part, greatly reduce LOC.
2024-07-05 01:50:57 +03:00
Azamat H. Hackimov
c5712208f6 CFILE: Additional unit tests for cfile functions 2024-07-05 01:50:57 +03:00
Azamat H. Hackimov
15ec76dd64 CFILE: Change cf_FindRealFileNameCaseInsenstive() to use std::fs::path 2024-07-05 01:50:57 +03:00
Azamat H. Hackimov
dad20b0830 CFILE: Add unittest framework 2024-07-05 01:50:57 +03:00
Louis Gombert
9263055e73
Merge pull request #482 from pzychotic/cmake-folders
Better project structure for IDEs
2024-07-04 18:36:03 +00:00
Azamat H. Hackimov
ee9e642a86
Merge pull request #474 from Lgt2x/enable-warnings
Enable all compilation warning on unix platforms
2024-07-04 21:01:39 +03:00
Louis Gombert
9ec18a240b Enable all compilation warning on unix platforms 2024-07-04 21:30:38 +02:00
Thomas Roß
12ec7c50c7 [CMake] Enabled the CMake property USE_FOLDERS to provide a more structured project list in IDEs with the help of set(CMAKE_FOLDER "...") calls. 2024-07-03 19:55:04 +02:00