Hello! So, this week I have done things that ranged across all my tasks. Recently I checked out our sister project, ResidualVM. ResidualVM's codebase is largely similar to ScummVM, but the main difference is the addition of capabilities to run 3D games. They also take regular snapshots from ScummVM to keep up-to-date. So, the work of RTL GUI which was merged in ScummVM was also present there.
When I was running the application with the Hebrew language, some popups and drop-down buttons looked quite different from the normal GUI. Upon a little investigation, it looked like paddings were being set wrong for the RTL-widgets set in the theme. This was because back when I was on my RTL task, I temporarily set a padding of "2" as a placeholder to check, and then completely forgot about it as the difference was ever so subtle. I'm glad though, that I found this, and opened a PR to fix it.
|English, proper paddings|
Last week I left off saying Eugene had some comments about my U32 task, so this was what I worked on next. After solving the review issues, I decided to review my PR more carefully once again, because many issues were being raised.
This time, I picked up on many things that could also be done and saw some things I had left out.
For example, when a user wants to add a game, they can choose a folder from a file browser. This file-browser can also be a native system open dialog, or a ScummVM custom browser.
So, for windows, ScummVM implements a small layer of Win32 API to implement this. The dialog has some labels which are also set to the GUI language.
Before, I had written some sloppy code (1 line of code change) and expected it to work to as it used to, without thinking too much about it. It was clearly very wrong, and the translations in the dialog were broken. Nevertheless, I worked on adding support to it properly. I already had text in UTF-32, but our Windows wrapper code didn't have anything to convert the text to an LPWSTR (16-bit Unicode characters). I looked up documentation online and followed it, implementing a UTF8ToUnicode. We have a conversion function for UTF32 to UTF8, and then by using the above function (internally calls MultiByteToWideChar for UTF-8 encoding), it was converted properly to LPWSTR. The implementation now looks proper.
|Russian translations for dialog title and "OK" button (The OK button has the label - "Choose")|
One of the issues raised was that I was converting a Unicode string back to a normal string because a class called StringTokenizer was involved. I don't know how I missed that, so I implemented a Unicode string tokenizer.
A StringTokenizer simply takes in a string and some delimiting characters and separates the words based on the delimiters present. So, If I have the string "Hello, World - Welcome.... to ScummVM" and provide the delimiters as - " ,-." - I will get the individual words ("Hello", "World"....), which I can simply search, for example, in a list - if it contains those words or not.
One example where they're used is in the game search filter. Let's say I have a game - "Reversion: The Escape, PC" in a list of 100+ games. If I type in either of those words, the search list should show this game. With everything going Unicode, now what would happen is if you have a game title with non-ASCII chars, like かわいい- and you start typing in か, the game with the title かわいい will show up in the search list. I'm not sure if we really support typing in with any other languages in ScummVM right now, but it is now future-proofed I guess!
Those were pretty much the main things I did for the U32 task. I also cleaned up the PR quite a bit, reviewed it with care so small things get out of the way.
Yesterday and today I was able to shift focus again to the detection task. The very first thing I did was to drop the previous few commits because the approach was wrong.
So, each engine has an overall engine template. Anything related to detection, the "MetaEngine" or any other related function is supposed to be defined here. It also contains function definitions from classes not declared here. So, my first guess was to restore the function definition to the original files. Say, "example.h" had the declarations, so "example.cpp" will have all the definitions. That's what I did, but I failed to recognize that functions were not defined in the so "example.cpp" for a reason. All detection related code from any classes is grouped over at detection.cpp, so the code overall has a nice structure to it. This also makes it easier for engine maintainers.
After a discussion, what I will now try to do is take code from "detection.cpp" and split it into another file - "detection-static.cpp", which the name suggests, will always build into the executable.
Finally, once again I arrive at the "createInstance" bridge. If you don't remember from last week, a small recap: createInstance is basically a function inside a MetaEngine - which instantiates the proper engine. So, if I am trying to launch the "Plumbers" game, it will instantiate the "Plumbers" engine.
The difficulty with this is that the function itself contains code that is not available in the executable. What I mean by that is,
Say I have an engine, which is used to run the game "exampleGame". This engine is named "exampleEngine".
When we request ScummVM configuration to build this engine as a dynamic module (explicitly linked run-time library), all code in "exampleEngine" goes into the "exampleEngine.dll" file.
Now, the previous dynamic system, everything was in the external library, so we could just load it, and then have "createInstance" instantiate the proper engine. i.e in this case, "engine = new exampleEngine". But now, the MetaEngine is always included in the executable, so that's a problem.
Why a problem? If I include "createInstance" class method inside the executable, it also has the line
"engine = new exampleEngine();"
What is exampleEngine? How will the compiler/linker recognize that, if the engine itself is in an external library? That's the issue of why this particular method cannot live in the executable.
So, what I am doing now, is basically making the createInstance method live outside the executable, and inside the .dll, while still making everything work as it used to.
I tried to approach this in various ways, but most of them had a flaw somewhere. Yesterday, I thought of a good approach, which will make minimal changes across engines and should work correctly. It's still a work in progress though, and no point in expanding on something that could be wrong. So, more on this next week!
I'll basically be focusing on implementing a way to bridge this gap for the next week, & That's it for this week!
Thanks for reading!