Hello! Some very nice progress this week I can’t wait to tell you about. Let’s just jump right into it!
So, last week I shared that even though I had something cooked up that was somewhat correct, it wouldn’t really be suitable as a proper solution. I also discussed briefly on what was the approach I was taking on next. Because the new work would require cleaning up a lot, I just set up a new branch and cherry-picked some of the commits that would be relevant.
The plan did work out, and after laying out the brief structure I explained last week, some engines started to show life again. For some engines, the story was a little different though.. but we’ll get to that next week because these might not be final, and I used my best judgment for them. Once the few engines were working well, I got started with porting all the engines over, and this week – I managed to convert them all to the new infrastructure! 79 engines in total, including the ones that are unstable! A very good bit of progress I would say! We have a Windows-CI set up on GitHub actions, and CI showed green light for the first time in forever! The step by step progress per engine turned out very nicely and was along the lines of what I wanted to do.
Now, how were the actual engines ported? Because most of these engines use AdvancedMetaEngine (which takes care of primary detection), the “detection.cpp” file, for, let’s say, the AGI engine just has something like:
class AgiMetaEngine : public AdvancedMetaEngine {
// Constructor, where we pass in the tables helpful for detection // and other things // Few utility naming functions // Some other helpful functions }; REGISTER_PLUGIN_STATIC(AGI_DETECTION, PLUGIN_TYPE_METAENGINE, AgiMetaEngine);
The last line is a macro that inserts some wrapper code and allows this plugin to build statically into the executable. The first argument for this macro is an ID, a unique identifier. Next, we say the type of plugin. We have MetaEngines, Engines, or Music type plugins at the moment. Last is the name of the class which will be created when loading/linking takes place.
Because we separated out connecting functions into a whole new class, we shifted that class and other engine-related methods to metaengine.cpp. in metaengine.cpp, the structure looks something like:
/* Engine - functions, which are related somewhat to detection, as in, they query information from Game description. class AgiMetaEngineConnect : public AdvancedMetaEngineConnect { // Connecting functions, like creating an instance, listing the savefile, etc. }; */
The methods that live inside here would basically take place once an engine plugin is loaded. So, for example, things like listing saves, creating an instance, initializing keymaps go here. If Plugin enabled as dynamic, we use the dynamic variant of the above macro looks pretty similar:
REGISTER_PLUGIN_DYNAMIC(AGI, PLUGIN_TYPE_ENGINE, AgiMetaEngineConnect);
which inserts the correct wrapper code (marks these as export symbols, etc).
The first field in the macro is the ID as I said before. When I was ported the first few engines and they were working properly, I wanted to check if the static version of plugins was building properly. At first, they weren’t, because in detection.cpp and metaengine.cpp, I had similar IDs. To solve this, I simply gave the ones in detection.cpp a new ID, and suffixed them with “_DETECTION”. The configuration script file needed a few changes as well, which were easy to incorporate.
For MetaEngines, the split was somewhat different, but this was seldom the case as only as many engines ever use MetaEngines. These differ in the way that they provide their own detection methods. An example is the Scumm Engine, which has a very heavy bit of detection code. This code is not only used for detecting games, but it’s also used when creating a game. A good part is that Scumm (or other engines which used to inherit from MetaEngine for that matter) have an internal detection method which is called during the detection of games while creating an instance rely on the internal methods and not the MetaEngine-detection-implementation itself. What this meant was we could safely separate MetaEngines & MetaEngineConnect, and provide a static copy of internal detection to both, so they are separated as intended, but function as-is.
Just yesterday, I cleaned up my history quite a bit and ordered it nicely so the MetaEngines and relevant code in ScummVM subproject were first, and then each individual engine commits were made. This would make it nicer to look at, and perhaps even make it easier for review. After that, I was thinking of opening up a PR because the work seems nearly complete. The title says some new things to do for a good reason, and that’s why I’ve decided to open the PR later when I incorporate, or at least try to incorporate the new changes.
What’s this new thing to-do? Basically, after all the engines had been ported over, I built a dynamic scummvm with all engines enabled. The file size of the executable is now ~13MB from the original ~11MB. That means a 2MB size has been increased, which might not sound much, but can be troublesome for the lower-end platforms. An example of this, I learned, was the Nintendo DS. So, right now, I am working on making the detection code pack themselves into a library.
With final evaluations approaching soon, the main/core changes are complete, so I’m pretty happy about that. When I finish the current to-do of packing the detection code into a library, I will open the PR. Hopefully, that should be around the next week. That’s it for now! This week I’ll be focusing on this new thing, cleaning up more, preparing small documentation as to how the new changes would look overall, which engines were somewhat irregularly ported over, and so on. I’ll also be starting with ResidualVM’s engines. More work to do, see you next time!
Thanks for reading!