GSoC Summary

Project description

The goal for the project was to finish the work on qdEngine and make all games based on it playable and completable. Milestones for the project were:

  1. Multiple MinigameManagers could be instantiated. Mini-games for dogncat are running.
  2. Games with advanced mini-games are supported.
  3. All games on qdEngine are supported.

Because I continued working on the engine since my first contribution at the start of March, I was able to finish the task in the first week on the GSoC period.

Thus, for the GSoC period itself, my task was to finish the work on existing engines.

What was done

The original goal for qdEngine was met and I was able to reach all milestones – all games are completable to the end. The news item with the engine announcement can be found here.

The second engine after qdEngine was SLUDGE. The engine was already very close to be done, so only I added a few minor enhancements:

  • Support for extended saves
  • Support for Return-to-Launcher and custom quit dialog
  • Fixed some crashes during autosaves

Following this, I worked on adding language support for the Teenagent game. At that time it only supported English strings, and my task was add support for Polish, Czech and Russian (fan-translated) strings. The challenge was that all language-related data was stored inside the executables, so I had to first extract them, and then modify create_teenagent tool, so that it generated the .dat file that contained the data for all languages in it. This task took quite some time, but in the end, I was able to extract all strings, pack them into dat file and make changes to the engine to support everything.

Shortly after this, I also added support for Polish voice-overs, the only version with voice acting.

After Teenagent, I worked on WAGE engine to support games made with World Builder game creation system. This included both fixing the bugs and also redumping the games, so that they are in right format (Macbinary). The latter took some time and iterations, however with the help of my mentor, we were able to produce the master collection and announce engine for the public testing.

After this I worked on playtesting and improving the MacVenture engine. I was able to fix a couple of blocking bugs, implement number of missing features and playtest games to the end.

Finishing the work on engine also includes taking screenshots, writing wiki pages and preparing news items. So in addition to writing code, I also helped with screenshots and wrote three news items for WAGE, SLUDGE and qdEngine.

Code merged

There were a number of pull requests created over whole period of GSoC. Below are some of the important ones:

qdEngine

Adding support for advanced minigames

Adding 32bpp support

Adding punycode support

SLUDGE

Add support for extended saves

WAGE

Various bug fixes

Adding fallback detection

More fixes

Teenagent

Adding language (textual) support for Polish, Czech and Russian

Adding Polish voice-overs

MacVenture

Bug fixes and improvements

What’s left to do

Finishing last bits of MacVenture:

  • Display Title and StartupScreen images on startup.
  • Extend MacDialog to support text input and use it everywhere in the engine instead of existing dialog class. This will make pop-up dialogs look more similar to original.
  • Sync Click-To-Continue button’s behavior with original. In other words, enable click-to-continue button when text inside console window needs to scrolled to be fully read to the end.
Conclusion

I really enjoyed my time spend with ScummVM this summer. It was my first time contributing to open source project and doing it with ScummVM was a great experience. I am pleased that I had a chance to work on a real world application used by players all around the world.

Working on this project helped me to improve my skills in navigating enormous codebases, reading and understanding other people’s code and correctly formulating and asking questions when get stuck.

Lastly, I want to thank project organizers at ScummVM team for selecting me and giving me a chance to participate in this program. Of course, I also want to say huge thanks to my mentor – Eugene Sandulenko, aka, sev, who guided and helped through this entire period. He was always there for help when I got stack and provided deep explanations when I did not know certain things. I also would like to thank other developers who reviewed my code, provided suggestions and pointed to mistakes. Finally, I am grateful to GSoC organizers for providing this incredible opportunity.

GSoC: Final Blog

Goals of the Project

The aim of the project was to integrate a File Integrity Service into ScummVM, along with a supporting application for managing the database. The main goals were:

  1. Populating the database with the detection entries used by ScummVM for game detection, followed by existing game file collections containing full MD5 checksums.
  2. Developing a utility for scanning game directories and generating data to further populate the database.
  3. Allowing users to verify their game files through this integrity service, and contribute new game variants.
  4. Building an application for managing the server and the database with role based access.

What I Did

  • A large portion of the work involved rewriting the codebase, as the existing logic for filtering and matching the filesets was not correct.
  • For ensuring correctness of code while matching old game collections, a lot of manual checking was required for over 100 different engines.
  • For the scan utility, I extended support for legacy Mac file formats (AppleDouble, MacBinary, etc.), ensuring proper matching with filesets present in the database.
  • For user integrity service, I worked on reporting information like Missing files, Unknown Files, Mismatched Files and Ok files. Further, I built a moderation queue system for user submitted files and also solidified the checks on user submitted data to allow submission of only valid data.
  • For the application, I added support for manually merging filesets, updating filesets within the application, improved search filtering and logging. Further, I added a configuration page for customising some user display settings and integrated Github OAuth with role-based access control (Admins, Moderators, and Read-only users).

Current State and What’s Left

The application is in a complete working state. All the workflows are functioning properly. The remaining step is to populate the database with all existing data so the integrity service can start operating officially.

Code that got merged

List of PRs that got merged – 

Server Side:

Github OAuth

Extending Web app features

User File Integrity Check, Web App updates and Project Restructuring

Scan Utility and Scanned fileset matching

Ruff formatter and linter

Macfiles support, Initial Seeding and matching with old game collections

Punycode

Readme Update

ScummVM:

Freeze issue for Integrity Dialog

 

Challenges and Learnings

The most challenging part was handling the variations across engines and game variants, and ensuring correctness in the filtering and matching process while populating the database. This often required manual validation of filesets. Working on this project taught me about the level of care needed to maintain the code and the importance of sharing the thoughts with the team. It was a highly rewarding experience working with ScummVM, and I am very grateful to my mentors Sev and Rvanlaar for their guidance and support throughout the project.

GSoC Final Work Product

Project Goals

The main goal of this project was to add text-to-speech, or TTS, to a variety of ScummVM engines. TTS enhances the accessibility of games supported by these engines and helps language learners. Furthermore, adding TTS to more engines standardizes the implementation of this feature, meaning the inclusion of TTS will be more consistent across engines. Adding TTS to an engine entails adding responsive voicing of text elements such as dialogue, menus, user input, objects, and credits, as well as adapting TTS to user actions and the functionalities of the games themselves.

What was Done

The original goal of the project was to add TTS to 12 engines, but I had enough time to add TTS to an additional 3 engines. Therefore, I added full TTS support to a total of 15 engines over the summer. In addition, I added TTS to 2 engines prior to the official start of GSoC, and I helped fix a few bugs for one engine.

Current State

All of my pull requests have been merged, meaning 17 engines now have full TTS implementations. Games that use these engines should have comprehensive and usable TTS.

What’s Left

All of my project’s goals, as well as a few stretch goals, have been completed. Nonetheless, some engines that support a wide variety of games, such as SCUMM, may need additional testing by end users. Any required changes found from this testing should only be tweaks to behavior: the core of the TTS implementations themselves should be complete. In addition, there are still a few engines left that need TTS support.

Code

Most PRs are for adding TTS to certain engines, but some are fixes for previously merged code. The following is a list of each PR I opened:

  1. TTS for Drascula: https://github.com/scummvm/scummvm/pull/6526
  2. TTS for TeenAgent: https://github.com/scummvm/scummvm/pull/6566
  3. TTS for WAGE: https://github.com/scummvm/scummvm/pull/6669
  4. Fix for Russian TTS for TeenAgent: https://github.com/scummvm/scummvm/pull/6722
  5. TTS for Cine: https://github.com/scummvm/scummvm/pull/6700
  6. TTS for CruisE: https://github.com/scummvm/scummvm/pull/6710
  7. TTS for Draci: https://github.com/scummvm/scummvm/pull/6742
  8. Fixes for TTS for CruisE: https://github.com/scummvm/scummvm/pull/6752
  9. TTS for MADE: https://github.com/scummvm/scummvm/pull/6779
  10. TTS for ADL: https://github.com/scummvm/scummvm/pull/6785
  11. TTS for Parallaction: https://github.com/scummvm/scummvm/pull/6795
  12. TTS for Prince: https://github.com/scummvm/scummvm/pull/6807
  13. TTS for EFH: https://github.com/scummvm/scummvm/pull/6820
  14. Bug fixes for EFH: https://github.com/scummvm/scummvm/pull/6821
  15. TTS for MM: https://github.com/scummvm/scummvm/pull/6835
  16. Czech and Polish TTS for TeenAgent: https://github.com/scummvm/scummvm/pull/6867
  17. TTS for SCUMM: https://github.com/scummvm/scummvm/pull/6856
  18. TTS for AGI: https://github.com/scummvm/scummvm/pull/6862
  19. TTS for Gob: https://github.com/scummvm/scummvm/pull/6880
  20. TTS for Got: https://github.com/scummvm/scummvm/pull/6888
  21. Fix for TTS for Got: https://github.com/scummvm/scummvm/pull/6900
  22. TTS for Hugo: https://github.com/scummvm/scummvm/pull/6897
Challenges and What was Learned

Ensuring TTS compatibility across numerous games, languages, and versions that a single engine may support was sometimes challenging to comprehensively address. Furthermore, some engines handle their text almost entirely with game scripts, which makes it more difficult to narrow down where text is being displayed and how to feed it to TTS. To address these problems, I had to test thoroughly, think about limitations and features that differ between games or platforms, and employ strategies such as recreating click boxes to properly voice text as the user interacts with the game. Thus, most challenges with adding TTS revolved around compatibility and logical voicing of text elements.

I learned a great amount this summer about working with a team, understanding and modifying code written by other developers, and writing code that fits into an existing codebase. I am now more comfortable with navigating and working on larger projects.

Conclusion

I enjoyed working on my Google Summer of Code project, and I found it to be a very entertaining and rewarding experience. I am happy that I was able to contribute something to ScummVM, and I hope that it will be helpful to users.

I would like to thank my mentor, criezy, for kindly guiding me throughout the summer, and sev, for guiding me as well. I would also like to thank all members of the ScummVM team that I interacted with for their patience and assistance, and the entire ScummVM team for their work on this application.

Expanding Director Engine compatibility in ScummVM

For the last 12 weeks I’ve been working on the Director Engine to increase support for it in ScummVM. Originally created by Macromedia, the Director Engine is under development for the last 9 years in ScummVM now. My goal was to inch ever closer to fully supporting games made using Director 4 and Director 5.


Goals for the Project:

I had outlined the following three major goals in my original proposal:
1. Completing support for all the workshop movies and implement all the stubbed functions.
2. Writing Director Files in ScummVM by implementing saveMovie lingo command.
3: Add support for titles SafeCracker and The Journeyman Project in the Director Engine.

Goal number 2 was the primary goal of the project, which I worked on first.

Goal number 3 was changed partially. Instead of working on the titles SafeCracker or Journeyman Project, I tried to work on Trektech.

Goal number 1 was changed. Instead of working on Stubbed functions and workshop movies, I worked on the ImGui visual debugger in the Director engine.

The goals for this project were regularly discussed with my mentor @sev.


What I did:

Before and during the initial few days of the coding period, I worked on the QTVR Xtra for the Director Engine. I implemented rendering in higher quality and warp (mode 0) for panoramas. I also implemented the swing transition while panning panoramas.

To add support for games like tkkg-1, I implemented the lingo command saveMovie which saves the current movie in its current state, effectively working as a save file.

I tried implementing support for movies as cast members which was an essential feature required for the title Trektech. However, I only went as far as loading them and processing lingo scripting for simple movies. I couldn’t get it to work for Trektech. Since, it proved too much for my level of experience, as per my mentor @sev’s advice, I left the work incomplete and pivoted to the next task.

I fixed the following bugs in Director.
1. Fix Duplication of cast members in case of multiple casts.
2. Avoid usage of  unreliable value LingoDec::Scripts::CastId.
3. Disabling event processing while b_alert is called.
4. Fix deprecation warnings in Director engine compilation.

I also made some upgrades to the ImGui visual debugger in the Director engine. Majorly including:
1. Rendering previews for some of the cast members.
2. Improving/refactoring the Script/Callstack window into the Execution Context window.
3. Improving the Score window to show continuation data.
4. Implement Loading/Saving ImGui state.
5. Reworking Functions window to use reliable references.
and a number of other small things.


The Current Status:

The saveMovie lingo command was successfully implemented. This was also tested and verified using the title tkkg-1.

Support for Trektech and movie cast members is incomplete. Simple test movies with basic lingo scripting work well. However, it is unreliable as seen by the crash in Trektech, as soon as it tries to load a movie cast member. I will continue working on this.

The ImGui debugger has seen a fair number of upgrades. However, it does need more work to be called complete. I still have a draft PR continuing the work.


Implemented code:

Here is a link to all the pull request that were merged during the period (18 in total).

Here is the link to the draft PR for ImGui improvements.


Challenges faced/Lessons Learned:

Director engine, as mentioned, is under development since the last 9 years. A lot of the development is already complete. Hence, it was difficult for me to grasp its large code base, given my limited experience with large projects. On top of that, My insistence on figuring out solutions independently proved harmful, sometimes resulting in slow progress.

The Director engine is a fun engine to work with. I learned a lot of concepts related to Software Development and Object Oriented Programming. I also learned how to use version control systems properly.  I also learned how to communicate programming ideas when there are multiple people working on the project.


I enjoyed working on ScummVM. So much so that I’ll continue contributing occasionally. I am thankful for the organizers of GSoC and my mentors @sev, @rvanlaar, @OMGPizzaGuy and @somaen, for guiding me through. I hope my contribution benefits developers as well as users of ScummVM.

GSoC Final Report

My project focused on extending ScummVM’s Keymapper system to a larger number of game engines. The Keymapper allows players to remap controls to their liking, but many engines in ScummVM still relied on fixed input handling. By integrating the Keymapper into more engines, the project set out to improve accessibility, provide a consistent user experience, and give players greater flexibility in how they play.


What I did:
I added Keymapper support to 24 engines, fixed a few bugs encountered during the implementations, and helped standardize keymapper action descriptions. This standardization reduces the number of unique strings in the codebase, easing the workload for translators.


The current state:
Keymapper support is now available in 24 additional engines, allowing players to remap controls in a wide range of games that previously relied on fixed input. Several of my pull requests have already been merged into the main ScummVM codebase, and the remaining ones are under review. Overall, the project goals have been successfully achieved, and the improvements are now part of ScummVM’s ongoing development.


What’s left to do:
All goals outlined in my proposal have been completed, I added Keymapper support to the 23(The first one was not part of proposal) engines I had committed to. Beyond the scope of the proposal, there are still around 40 engines in ScummVM without Keymapper support, which could be future work for anyone interested in continuing this effort.


List of PRs:

  1. Toltecs keymapper: Pull Request
  2. Sludge keymapper: Pull Request
  3. Supernova keymapper: Pull Request
  4. Voyeur keymapper: Pull Request
  5. Titanic keymapper: Pull Request
  6. Normalize keymapper action descriptions: Pull Request
  7. Sword25 keymapper: Pull Request
  8. TeenAgent keymapper: Pull Request
  9. NGI keymapper: Pull Request
  10. Buried keymapper: Pull Request
  11. Access keymapper: Pull Request
  12. EFH keymapper: Pull Request
  13. Sherlock keymapper: Pull Request
  14. Neverhood keymapper: Pull Request
  15. Prince keymapper: Pull Request
  16. Lab keymapper: Pull Request
  17. Petka keymapper: Pull Request
  18. Queen keymapper: Pull Request
  19. Fix capitalization in Queen keymapper action descriptions: Pull Request
  20. Pink keymapper: Pull Request
  21. Drascula keymapper: Pull Request
  22. Chamber keymapper: Pull Request
  23. Make EFH keymapper table use POD and avoid global constructors: Pull Request
  24. Hypno keymapper: Pull Request
  25. DM keymapper: Pull Request
  26. Private keymapper: Pull Request

Any challenges or important things you learned during the project:
Each engine in ScummVM handles input differently, so I had to study and adapt to new codebases before adding Keymapper support. In doing so, I often uncovered and fixed unrelated bugs. Working on a new engine every 3–4 days also greatly improved my ability to read, understand, and modify existing code, and gave me confidence in working with large, mature projects.


Conclusion:
This project successfully achieved its goals by bringing Keymapper support to 24 engines in ScummVM, making input more flexible and accessible for players. Along the way, I learned how to work effectively with large codebases and contribute to a mature open-source project. I’d like to thank my mentors and the ScummVM team for their guidance and support, and GSoC for giving me the opportunity to work on a project that will benefit both developers and players.

Prepare to Descend Deep Into the Mine to Uncover Its Dark Secrets

The ScummVM team is happy to announce full support for the first-person survival adventure Penumbra: Overture!

Step into the boots of Philip, who is drawn to Greenland in search of answers after receiving a letter from his long-lost father. Once there, you find yourself trapped inside an abandoned mine… with no way out but deeper in.

The game is fully 3D and presented in a first-person perspective, featuring elements of stealth and physics-based puzzle-solving.

If you own a copy of the game and want to help test this release, download a daily build and be sure to read our testing guidelines.

Don’t forget your torch. You’re going to need it.

Another upgrade to the ImGui Debugger

For the last week of GSoC, I was working on some more improvements to the ImGui Debugger in the Director engine. Making the ImGui debugger as close to the original Director engine as possible will be very helpful in adding support for games in the future.

The first thing to do was to revamp the Functions window. It used to show all the handlers from all the scripts in the window in a single table. Since, that was not only messy and not properly navigable, @sev asked me to revamp it so that there are two views:

 

 

 

 

 

One: that shows all the handlers just like how it was shown previously and two: one that shows each script, and each script (‘Lscr’ context) and under each script we have all the handlers in that script. This allows us to navigate between scripts very easily. This also means, in the second view, the filtering works better, i.e. we can filter out all the handlers with a certain name (e.g. mouseUp) or those associated with a particular cast member (say no. 123) easily.

After that, we noticed that some of the scripts didn’t show the cast member number in the Execution Context window properly (e.g. -1 for the topicmaker:mnew in the screenshot):

Now, the cast id (even though present in the ‘Lscr’ data stream, is not reliable) is fetched from the associated cast member. Since cast IDs and script IDs are linked together, we can map the script ID to its corresponding cast ID. But, it was possible that some of the cast members are not loaded, because of lack of support or some error (e.g. Picture cast member). Hence, at first I thought, forcing the loading of their cast member info might solve this problem. However, I was wrong. But I thought it might still be a good and harmless addition, hence I made a PR.

It turns out that some of the ‘Lscr’ contexts are factory scripts, i.e. they have a parent script (which is associated with a cast member) and the handlers in the current script context are called in reference to the parent’s cast member. As you can see from the following screenshot of LCARS___.dir loaded into the origin Director engine, the handler `topicmaker:mnew` is part of a movie script (cast ID: 1285):

Even while dumping the scripts, ProjectorRays/ScummVM dumps the handlers in the current script as part of the parent script and completely ignores the current script (the one without a cast member associated):

This is the list of all the parent scripts and their child script:

“`
Who is: 236, whose parent: 89
Who is: 239, whose parent: 93
Who is: 232, whose parent: 234
Who is: 188, whose parent: 599
Who is: 597, whose parent: 623
Who is: 216, whose parent: 624
Who is: 21, whose parent: 646
Who is: 230, whose parent: 657
Who is: 26, whose parent: 721
Who is: 131, whose parent: 722
Who is: 24, whose parent: 723
Who is: 179, whose parent: 725
Who is: 131, whose parent: 727
Who is: 163, whose parent: 728
Who is: 199, whose parent: 729
Who is: 131, whose parent: 730
“`
Hence, the solution was to not show the associated castID but rather the script ID, which is unique to each script. Hence, it required storing the parent number and the script number in the ScriptContext class, and show that in the Execution Context window. This solved the problem. @sev then asked me to change all the references to a handler in a similar way, including the way we name the dumped scripts. This honestly took way too much time to figure out.

Also, the scripts are now shown in a separate window when we click on a handler in the Functions window rather than showing them in the Execution Context window. Hence, we can see as many scripts as we want at the same time.

Also, the handlers in the call stack are now selectable. You can click on them to jump to the exact byte code in the script shown below in the Execution Context window. To make the scrolling work, I had to include a separate boolean in the ImGuiState struct.

After that, there were a bunch of minor issues, like the scrolling in the Execution Context window when we jump to the definition, sanity checks for fetching `ScriptContext` through the handler Director::DT::getScriptContext, marking the script dirty when a button in the control panel is placed, and some other stuff too minor to notice here.

Also, in the Score, the original director shows whether or not a sprite changes in subsequent frames. Like follows:

I was working on adding a similar functionality in the Score window, but I’m only halfway there.

I’ll be adding the rest of the functionality in the next two days.

Hence, overall a slightly less than average week. I was busy over the weekend for the academic project for final year (my faculty advisor is not happy with our progress). Initially I planned on making this post my final submission, but later decided against it. I’ll be making a separate post underlining all the progress that I made over the last  12 weeks as my final submission.

Week 12

 

Last week was mainly spent by fixing left-over bugs from previously worked engines: WAGE, MacVenture and SLUDGE.

At the beginning of the week, me and Sev finished work on redumping and preparing ultimate archive of WAGE-based games. Finally, after multiple checks the we were able to prepare the collection and release it on the site, together with the engine announcement. However, a couple of issues was reported by the devs, so I returned back to the engine to fix them. In particular, I had to fix issues with closing the game, where confirmations pop-ups were not really working, i.e. the games were not closing. Also, for some games, closing them in midst of playing sounds resulted in crash, because the thread for audio was referencing the deleted engine object. Lastly, there were crashes due to null pointer accesses in scripts, which are could be either due to buggy scripts or due to engine issues. There is a possibility for the last one, since the game that was crashing (Mormonoids from the Deep) also throws exception in the Java codebase, which was ported to ScummVM.

Another engine to which I returned was SLUDGE. There was a PR by ccawley2011 to add the game (demo) called Otto Experiment. However, the problem was that it was crashing at the startup. The problem as it turned out was that the code was not looking for the file inside the game directory, only in the save game dir. Also, in general, the support for reading .ini files was missing. This was mainly used for language setting, some graphical preferences and so on. This feature appeared to be rare in general, however it was used in Otto Experiment and Cubert Badbone, so it must have been dealt with.

Last but not least, I did some work on on MacVenture. There was a few a differences with the Mac versions that needed be done: main game window names (which were not upper-cased) and console window.

Week 12: Keymapper Support for Hypno and Dungeon Master

This week I worked on the Hypno and Dungeon Master engines. I also got my Chamber keymapper PR merged 🎉.


Hypno Engine

Working on the Hypno engine felt a bit nostalgic—it was actually the first engine I touched in ScummVM when I fixed a small bug as an intake task for GSoC.

The engine supports three different games, each with its own input handling. Because of this, I had to create separate keymaps for each game, rather than a single shared one.

Apart from that, the implementation was fairly straightforward. The main tasks were:

  • Disabling the keymapper in certain sections where the game uses full keyboard input

  • Enabling/disabling keymaps for some of the menus

Nothing particularly tricky, but it was nice to revisit the engine where my GSoC journey began.


Dungeon Master Engine

Dungeon Master was another unannounced engine that I added keymapper support to. Fortunately, it didn’t have any blocking bugs or missing features, so I was able to test it thoroughly without issues.

The engine came with a decent number of keys to map, but overall the process was smooth and didn’t pose any significant difficulties.


Wrap-Up

This week, I:

  • Added keymapper support for Hypno and Dungeon Master

  • Got my Chamber PR merged 🎉

Week 12

Welcome to this week’s blog. This week, I added features related to updating metadata as well as file data directly from the application UI, along with some smaller fixes and improvements.

For any fileset, you can now update metadata fields directly from the UI. For user filesets in particular, there is an additional step of adding metadata first particularly gameid and engineid as they require creating entries in separate tables. To make filling metadata easier, I also added a dropdown feature that displays all existing values for a field from the database. This way, moderators can either type in a new value or directly choose an existing one. In addition to metadata, I added functionality to update individual files as well. This can be useful for tasks such as manually marking a file as detection file or updating other fields.

For better reliability, confirmation dialogs have been added for most buttons, such as deleting/updating files and adding/updating metadata. Further a separate button has been added for deleting the entire fileset. Another improvement is the ability to delete all filesets in bulk that appear in a filtered search result in the fileset search page.

To enhance logging for scanned files, a new field called data_path has been introduced. This field stores the relative path of the game directory, which is particularly useful when multiple files are scanned at once. This information can later be included in scan.dat related logs.

Lastly, I added an endpoint for sending a fileset ID as a mail notification. This is suppose to be triggered from the mail server whenever a user submits any fileset-related information, using a predefined mail structure in the ScummVM application. (This feature has not yet been integrated with the mail server.)

Week 12: Got and Hugo

Introduction

This week, I opened PRs for adding text-to-speech to Got and Hugo. They were relatively simple engines, and neither had any major challenges.


Got

I started this week by finishing TTS for Got. As previously mentioned, Got was quite simple for TTS: most of its text was easy to locate in the code, and text was rarely primarily handled by the game scripts. Thus, most of the game’s text could be voiced rather easily. For cleaner voicing, I included checks for when the score, jewels, or keys change, allowing their values to only be voiced when they change; delays as the credits are voiced to prevent them from moving too quickly for TTS to keep up; and voicing of dialogue as soon as it is started, so that it syncs well with the text while it appears one character at a time.

Nevertheless, one consideration for Got was the best means of cleaning text. In most cases, newlines break up sentences in dialogue, which results in choppy voicing if they aren’t replaced. However, some dialogue, such as signs, use newlines instead of punctuation to break up distinct sentences. If these newlines are replaced, TTS awkwardly pronounces everything as one quick sentence. My solution to this issue was to keep the newlines only if there are two or more in a row, as this is usually the case for sentences separated exclusively by newlines. Singular newlines tend to break up whole sentences, and thus should be replaced.

Ultimately, Got was one of the simpler engines that I’ve worked on. It required some care for properly cleaning up text and guarding against awkward voicing, but it otherwise offered few unique challenges.


Hugo

After Got, I worked on adding TTS to Hugo. Like Got, Hugo was a fairly simple engine for TTS. Its games are straightforward and similar to each other, which made it easier to implement functional TTS for all scenarios. Furthermore, it has few unique procedures of displaying text, so voicing most or all of its text only required adding TTS calls to a few methods. Nevertheless, Hugo required some consideration for its dialog boxes. Unlike most other engines that I’ve worked with, Hugo displays a considerable amount of its text in ScummVM dialog boxes, which have their own TTS. This means that opening or working with some dialog boxes, like the top menu, stops all TTS. Stopping TTS in this manner, however, can interrupt voicing of the sound setting, which is shown in Hugo’s score line. Voicing it as soon as it changes doesn’t work properly, as in many cases, the top menu is immediately opened again, thus interrupting the voicing. Therefore, my solution was to keep trying to voice the new sound setting for as long as the cursor is in a position to open the top menu. In this way, once the top menu finally fully closes and doesn’t open again, the sound setting will be voiced.

Other aspects of Hugo were rather simple. It mostly entailed implementing more TTS for the aforementioned dialog boxes, as their built-in TTS only voices text as it’s hovered over and only one line at a time, and it seemed to me that these boxes needed to be voiced as one clean paragraph or sentence and as soon as they appear; voicing scoring changes; and correctly queuing voicing when dialog boxes, user input, and scores are voiced, to prevent them from interrupting each other as dialog boxes appear.

In conclusion, Hugo was fairly simple. Because its games involved few different means of displaying text and simple controls, it didn’t offer that many unique challenges.


Conclusion

This week, I finished adding TTS to Got and Hugo. Both of these engines were simple to work with, and they didn’t have any major caveats or challenges.

Announcing support for World Builder-based games

After many years of development, games made with World Builder are ready for testing. The World Builder creation system was released for the original Macintosh and was extremely popular among developers. As such, we're announcing that over 160 games built on the engine are ready for public testing in ScummVM. Notable games made with World Builder include:

  • Ray's Maze. The game follows Frank Farley, a part-time adventurer, who finds himself in a Maze full of dangerous monsters and deadly traps. The objective of the game is to solve puzzles and escape the maze.
  • Radical Castle. You are given the role of a squire, who must bring back the stolen "Oracle" to the King to escape a fatal punishment.
  • Enchanced Scepters. The first game created using World Builder, and one of the few commercial games made with it. The player must find fire, earth, air, and water scepters and bring them back to the castle.

Most games made with WAGE are either freeware or shareware, and for your convenience we've collected all titles with these types into one big downloadable archive. So grab it from our game downloads page, get yourself a daily development build, and start your journey. As always, if you happen to have any issues, please submit the bug reports to our issue tracker. Lastly, contact us if you have some other unrecognised games or a new demo.

ImGui: Refine the debugger to a usable state

This week again, I continued working on the ImGui visual debugger in Director, mostly working on small bugs and broken features caused by the work in the previous weeks.

The Execution Context window shows the lingo scripts being executed. To make it show multiple handlers from the same script at once, I had made changes that broke the navigation. Stepping in, stepping over and stepping out in the control panel didn’t work properly, jumping multiple instructions at once. The problem was that startOffsets of the script weren’t getting stored, since I needed to render multiple handlers, each with a separate ImGuiScript object. These startOffsets store the offsets of each line of script. While stepping in/over/out, the lingo program counter is compared with these to find out which line is getting executed at the moment.  I had to make sure that the ImGuiScript object associated with handler currently being executed persisted and was passed by reference to the renderScript() function so that it will store the startOffsets properly. Also I had to make sure that the _script->_dbg._isScriptDirty flag is set after all the scripts are rendered. Previously it was set to false after rendering the first script.

In the lingo scripts in the Execution Context window, if there is a call to a function, you can press the function to go to its definition. However, the search for the handler was flawed. The value we were passing to the function that fetches the ImGuiScript as the castId of target script, was wrong. It took me some time (and some messing around with ProjectorRays) to figure out that this is the Id (or index) of the script (in cast of a localcall, this is the index of the script in the script context (consisting of scripts in the same file/’Lscr’ resource), whereas in an extcall it was the index of the script in the global context (consisting of all scripts)).

This is obviously wrong, hence I had to find out the actual castId of the script which contains the handler, since castId and scriptId are coupled, I can find the castId using the scriptId and pass that, which worked as expected.

During this, I also realized that for some reason, some of the scripts weren’t showing up in the debugger at all, apparently for no reason at all. Upon some investigation, I found out that the way the scripts were fetched was, that the LingoDec decoder reads these scripts and the corresponding data. One of which was the castId of the script, which it turns out isn’t reliable. It may be wrong, it may have duplicates, can’t be trusted. Hence, instead, from the HashMap that maps the castID of a cast member to its script id, I fetch the castID and use that to fetch the script, which worked like a charm. This PR should explain the issue in detail. This also solved an issue where, when asked to dump the scripts, the names of the files dumped and the scripts didn’t match at all.

I had to also solve scrolling issue in the Scripts window. After jumping to a handler, if the script contained only one handler, the scrolling worked fine, but in case of multiple handlers, it used to jump to the last handler. Had to introduce a _scrollTo flag which was set only when rendering the current script.

I also got rendering of text and shape previews this week. In order to render them, I was at first checking which channel had the text/shape to be rendered, and pass that channel and a ManagedSurface to Window::inkBlitFrom(), and showing the surface in the preview. However, obviously, this meant that if a shape/text is not on the stage at the moment, it won’t show a preview. Hence, I had to prepare a dummy channel with the correct sprite and relevant properties (e.g. thickness, foreground color, background color, pattern, etc.) and then blit it to a temporary surface for preview. This honestly took some time to figure out.

Other than this, there were some minuscule things, too unnecessary to mention here.

Hence, overall a pretty normal week again. Next week is the final week for coding after which there is the final submission. I hope to have done enough to count the project as a success.

This week also brought good news in the form of a job offer. In most engineering colleges in India, recruiters visit the college to hire final year students as graduate trainees. I was lucky enough to be selected at one such offer. Now that I have this security, I can continue to contribute to ScummVM even after GSoC. Not as regularly but over weekends and holidays. Working on ImGui has been fun but I wanted to directly work on making a game work in ScummVM’s Director, similar to how @rvanlaar was working in SafeCracker. Couldn’t unfortunately succeed at that during GSoC but I’m planning on doing so afterwards. Looking forward to that!