Start your engines

Last week I listed a few issues that were on my “TODO”-list, well of course some progress has been made, so without further ado:

Volume-settings:

While formerly volume-settings were completely ignored, now I’ve removed the internal settings in the engine for sfx/speech/music-volume, and mapped those directly to the matching ScummVM-settings, which means that changing the volume in the GMM, or in-game will show up nicely in both places. Some games are a tad aggressive on updating the sliders, which makes for a bit of jumpiness on their sliders, but it works atleast.

The engine also has a concept of “master-volume”, while ScummVM doesn’t, so I ended up deciding that the most consequent way to solve that, was to simply apply that as a multiplication on the other values, thus setting Master to 50% when Speech is at 50% would yield 25%, and still get that updated when the values are changed through the GMM.

Sound-format-support:

I added in RAW-WAVE support (no MSADPCM-support yet), which means that the white chamber now also plays all it’s sound-effects. The engine will error out if it meets any other formats, a solution I chose to be able to pick up on missing format-support if some game needs any more than this.

TTF-Fonts:

As I said last week, the fonts now draw without being too dark, it remains to be checked if the line-lengths still match well (seems that Rosemary has a few problems with lines overflowing without increasing the background for the text.

Detection:

Ok, so this is where I’ve put a lot of my work the past week. While most of the games I have are added with proper MD5-detection entries, one of the bigger selling points of this engine is the ability to make your own games, and, well having to recompile ScummVM with new MD5s for every iteration of your development would be kind of a hassle, which is why I added a fallback-detector. Currently this works like follows for any given folder.:

  1. If the folder doesn’t contain a “data.dcp”-file ignore the folder
  2. Otherwise, start up the basic initialization of the engine.
  3. Add in the DCPs in that folder to the engine (although, “data.dcp” should be enough)
  4. Parse “startup.settings” to get the GAME-variable (usually “default.game”)
  5. Parse the file defined from “startup.settings”‘GAME-variable, looking for NAME and CAPTION.
  6. Then work with those vars to create a gameid and a game-description (using the extra-field of the detection entry to fill in the Caption if it differs from the game-name)

This gives a bit of overhead for each game, as quite a bit of the engine needs to be loaded to use the file-manager to read from a DCP, and the same holds true for the parser used, in all fairness this only happens whenever a “data.dcp” is found in a folder AND that data.dcp doesn’t match a known MD5, but still, long-term I guess a more clearcut solution would be in order. The only file that really gets parsed by the engine-parser right now is startup.settings though, while default.game gets put through Common::StringTokenizer simply because I only need 2 fields of that file.

One problem with this solution, is that I don’t use the StringTables in the engines, thus any localized captions will not be localized but instead contain the placeholder-string. In any case this isn’t too big of an issue, as using non MD5-listed games should become the rare case for developers, and the game name can always be added explicitly to the MD5-based detection.

File-access:

Changing the engine to be able to do detection without loading up the ENTIRE kitchensink of classes, while working with an explicit folder, lead me to investigate the file manager-system further. I had to change the use of SearchMan into a system of explicit FSNodes, which means that now paths for archive-less files are parsed with FSNodes, and all DCP-Packages now carry a FSNode to their location. (Instead of opening them with SearchMan when needed).

This might sound like an odd solution, but it has a decent use case, a few games have a “language” subfolder, that contains localizations for multiple languages, with a SearchMan-based solution I ended up registering ALL packages there, thus often ending up with czech ingame-text (alphabetic ordering of files…) To avoid this I needed a special-case for the “languages”-subfolder, filtering the dcp’s there, to only load the really necessary language. Right now this is hardcoded to be “english.dcp” only, but it should be quite possible to use the language specified in the game descriptor to select properly.

Variable-renaming:

While I still find the odd variable with the wrong convention, I have handled most of them now, one of the bigger changes was replacing the semi-global variable “Game”, which basically is a reference to the main “CBGame”-object, that every object carries around with it, that was left behind after the big rename a few weeks ago, mainly to make sure no big issues arose. But it has now been renamed to _gameRef.

I also changed all the class-name-conventions, removing the C-prefix and expanding on the classnames, thus any CBClass became BaseClass, and CAdClass became AdClass, and CSysClass became SystemClass, and so on. This was also followed up with renaming the entire file-hierarchy, to follow one filename-convention (i ended up with all_lower_case.{h,cpp}, as I’d had far too many case-typos when jumping between OS X and Linux in this project, this should atleast make it easy to remember the case-choice for any wme-filename).

Additional game detections added:

I added in quite a few more MD5-entries, to have more games to test with, here are the games I remember of the top of my head:

Note: Not all these games actually work, for reasons stated below in the “Remaining-issues” section.

Remaining-issues:

  • Videos still desynch, something I won’t be looking much further into in this GSoC, as the videos are a bit outside the main scope of this project, and well, the same issues still happen in Sword25, from where I got the video_decoder I’m using anyhow.
  • Dirty-rect rendering is still sketchy at best. (and thus disabled by default.
  • Interlaced PNGs are not yet supported, but that is also a bit outside of my control, I did open up a semi-complete pull-request that added more LodePNG-code to the PNG-decoder, but it still has a few files it chokes on.
  • 32 bpp BMPs are not supported in ScummVM, shouldn’t be impossible to implement, as I already did some tweaks to work past the crash that ensued (simply skipping the fourth byte of every pixel in the BMP atleast yields some results).
  • Non v.1.1 JPEGs are not supported in ScummVM, this I haven’t worked or looked any on, but it blocks a few games from even starting.

A picture says more than a thousand words

…which should put this blog entry far beyond 10 000 words. There has been a bit of progress with the Wintermute-engine, preliminary support for graphics, sound and I/O is in place, but it is far from perfect, or finished in any way, shape or form.

Right now, the sound system only allows playback of OGG-files, and it only does Play() for them, which was a rather simply task to add in, simply to verify that the sound system still works after having been stripped down from WinterMute Lite, either way no further work is planned on that part for atleast a few weeks.
I also added in some quick hacks to make the engine draw inside ScummVM, right now this is done in 24 bit hardcoded blitting, and was mainly done to see what had to be done. At this point it might be worth noting the work that was done on WME Lite prior to attempting to merge it into the ScummVM-tree as a branch. I started off by forking the original WME-Lite repos onto Github, then I went on to strip out all the dependencies (BASS, Boost, SDL2), as well as removing as much as possible of the “forbidden”-bits (ScummVM doesn’t allow direct usage of the C-APIs for file-accesses and random number generation among other things). As I went on, i ported over as much as possible of the ScummVM common code to WME Lite, until I reached the point where I might as well move the WME source over into my ScummVM-fork.

One of the things I did quite early, was to try to use the ScummVM-image loaders, as opposed to the SDL2-code that was used already in WME Lite, I made that kind of work, but transparency proved problematic for now. I picked the game Dirty Split as a test case for the moment, here is how it looks:

This is how the inventory in Dirty Split looks in the original prebuilt WME Lite
… and this is how it looks in my modified WME Lite-version, that uses the ScummVM image loader.
Now, for the first ever image of a Wintermute-game running inside ScummVM:
Yup, this is ScummVM, although it isn’t really obvious from the headline. Notice how the fence is wrong, and the transparency is off in all sorts of different ways.

The reason for all those interesting artifacts, is mainly that I only added a quick-fix for the colour-keyed transparency, but didn’t do anything for the alpha-channel stuff yet. Keen eyes might also notice that the character is a lot bigger in ScummVM, although this is the very same scene, with no movement done yet. This is another case of missing features, right now any bitmap that asks to be drawn, is drawn at it’s full size, no matter what it actually says about the wanted size. This gives a few rather odd behaviours at the moment, as for instance, walking away from the screen isn’t really obvious:

This is how walking up to the door looks in WME Lite (with a few of my modifications)
… and this is how it looks in ScummVM at the moment.

Clearly, the model’s need to scale appropriately, but, atleast input works well enough to get the character to move over there. The action-menu for Dirty Split reveals a few more of the transparency-quirks:

in ScummVM
in WME Lite (with my modifications)
I’ll be looking into solving these issues as I implement a more proper drawing-solution in the weeks to come.
Oh well, that’s about it for now, I’m off to do my exams, so what better way to end of, than to show how the three variations of the game look when you try to close it? Yes, there are a few minor differencies her, as I didn’t go through the menu in ScummVM, but simply Ctrl-C-ed the terminal session.
ScummVM
Modified WME Lite
Original WME Lite

 

A beginning

Since I started thinking about approaching this task, I’ve been doing a little work on the WME Lite code base. I originally forked that repos, and started removing the bits I knew that wouldn’t work with ScummVM, which mainly meant stubbing all the dependencies away (Boost, BASS, SDL2), and getting to grips with where STL was used (as ScummVM doesn’t allow me to use those).

I then did a bit of “reverse-porting”, copying over pieces of ScummVM to that repos, so that I could start replacing pieces of WME-code that depended on things that aren’t available in ScummVM, with the proper ScummVM-solutions. This worked up until a certain point, namely getting files to actually load (that would require copying over LARGE amounts of ScummVM-code). At this point I’d gotten to know the WME-codebase a bit better, and also untangled a bit of the header-dependencies that was there (which was usefull, to avoid having to copy the ENTIRE codebase in one go), to the point that I could start copying the files over to a branch in my ScummVM-fork.

This led to a day or so of resolving problems relating to common/forbidden.h (I hadn’t purged all the STL/FILE-related pieces of code, since the main reason for moving on from a fork of WME, to a fork of ScummVM, was to get files loading). Additionally I also had to follow the “HOWTO: Engines”  guide in the ScummVM-Wiki, to get the connections correct with the rest of ScummVM

But, in the end, I managed to atleast get a repos that compiles, and links in-tree. Right now, it even detects the game data, and should be just a few hours away from being able to get the scripts out of the data files, to start running the main loop of the engine.

This puts me quite a bit into stuff that was planned a bit further down the road in my GSoC-timeline, but sometimes things tend to happen in rather different orders than what one actually plans, there is still work to be done for what was planned as the first week’s work (Refactoring), but happily, I’ve gotten some help from Sev with automated renaming of variables, which should save me a day or two of manual labour. (Combined with some application of astyle, this atleast gets me of the start line for making the code base follow the ScummVM code-formatting guidelines).

In closing:
I might not be getting too much work into the next few weeks, as I have exams coming up, but I do plan to get the game data files at least loading, and hopefully to start looking through the files for any code formatting-breakages in the upcoming time.

Einar Joha