This week I worked on a bunch of small bugs with the saving Director Movies PR, and the movie cast member. This was one of the least productive weeks up till now.
The save files in ScummVM are stored at a specific location given by the configuration manager at
ConfMan.getPath("savepath")
This is the only directory that is writable. The game directories are not writable. The save file needed to be stored with the format:
<target-name>-<savefile-name>.dir
However, since the file is now stored at a location different than the _gameDatadir
, while loading the movie, we need to add the movie(s) in the SearchSet
which is a list of all movies in the game directory sorted by priority of loading. The priority of the saved movies should be greater than movies in the game directory. Which was an easy enough of a concept to understand. However, Director engine already has an implementation for game quirks, in the CachedArchive
which tries to load game quirks (specific archives, text files). @sev wanted an implementation similar to that. But, instead I spent a lot of time trying to implement my own approach. That resulted in a lot of time wasted. Finally, @sev intervened and explained to me in detail what was to be done.
The method was to create a separate sub class of class Archive
, named SavedArchive
and store a hashmap of expected paths (e.g. INTRO.DIR) mapped to saved movie paths (e.g. tkkg1-win-INTRO.DIR) and save this archive with higher priority in the SearchSet
at the startup of the engine. So, when asked to load a file, the SearchSet
first looks in the saved archive before checking the game files.
Apart from that there were a bunch of small fixes to the PR:
– Instead of saving the _mainArchive
, save the _currentArchive
– Start writing multiple casts, and their cast members
– Delete the generated resources to avoid memory leaks
– Implement the stubbed computeChecksum()
function
– Write external bitmap resource correctly with zero size
– Create a separate file `archive-save` for the saving code
Also, I opened a very small PR for fixing a bug while duplicating a cast member from a one cast to another. The problem was that we were looking for the source cast member in the target cast.
On the movie cast member task, I made little progress. Until last week, I was processing lingo scripts for the movie cast member correctly. I got to testing trektech-win this time, and it turns out this was not enough. The game was crashing as soon as the movie cast member finished loading and processed its first script. The reason was that in Director, the lingo execution is global. The movie cast member shares the global variables of the main movie. Hence, the scripts of the movie cast member must also be processed as if they are part of the overall lingo execution (with reference to the movie cast member). Hence, Window
class (which processes input events and holds the lingo state) and lingo processing are too intricately tied together. Creating a separate SubWindow
for the movie cast member messes this up. After the movie cast member jumps to a frame, returns from Lingo::execute()
it freezes its state as follows:
After freezing, it switches the lingo of the global window.However, since we’re processing the movie cast member, the lingo state of the movie cast member’s window should be the one to freeze. But instead it freezes the main window. This results in numerous segmentation faults. This will require in-depth knowledge of the lingo execution, hence instead of coming up with a wrong way to solve this problem, I asked @sev to switch me to another task.
One thing that I did end up fixing was when we switch the movie in the movie cast member, the previous movie needed to be deleted before loading the next movie.
After that, yesterday @sev gave me a set of three new tasks. Out of which, the first one was that one of the tables in the ImGui visual debugger for Director was getting generated without IDs causing a runtime error. I couldn’t reproduce the bug, so I moved to the second task.
The second task was that the lingo scripts being dumped with --dump-scripts
flag on, were misnamed. The problem was that we were writing filenames as: <movie-name>-<scriptType>-<castId-of-script>.lingo
But the castId
of the script was being written wrong. Instead of 1 we had 65537 (65536 (2^16)+1), instead of 2 we had 65538 (65536 (2^16) + 2). I suspected that the castId
must be being read incorrectly. Sure enough, the castId
was being read as: /* 44 */ castID = stream.readSint32BE();
Upon inspecting the hex dump of the movies I found that, the castId
was a 16 bit-entry rather than 32-bit. The 16 bits before that were unknown and changed between 0x1 and 0x0.
D5 MovieD4 Movie
In each of the screenshots, the 32 bits being read previously as castId
.
Hence, it needed to be changed to
/* 44 */ unk43 = stream.readSint16BE();
/* 46 */ castID = stream.readSint16BE();
Which works perfectly.
Despite this, overall, it was a pretty disappointing week. It’s ironic that this is the longest blog I’ve posted till now (by word count).
@sev also pointed out that I’m not reporting my progress regularly, which I intend to improve upon in the upcoming week. Hoping for a better next week.