{"id":105,"date":"2026-08-18T10:57:27","date_gmt":"2026-08-18T10:57:27","guid":{"rendered":"https:\/\/blogs.scummvm.org\/andy\/?p=105"},"modified":"2026-08-18T10:57:27","modified_gmt":"2026-08-18T10:57:27","slug":"the-final-post","status":"publish","type":"post","link":"https:\/\/blogs.scummvm.org\/andy\/2026\/08\/18\/the-final-post\/","title":{"rendered":"The final post"},"content":{"rendered":"<p data-path-to-node=\"3\">GSoC 2026 Final Report \u2014 Finishing Incomplete ScummVM Engines<\/p>\n<p data-path-to-node=\"4\">Contributor: Ion Andrei Cristian \u00b7 Organization: ScummVM \u00b7 Coding period: 25 May \u2013 17 August 2026<\/p>\n<p data-path-to-node=\"5\">This is my final work product for Google Summer of Code 2026. It collects everything I worked on this summer in one place: what the project set out to do, what actually landed, where things stand now, and what is still open for whoever picks this up next.<\/p>\n<p data-path-to-node=\"6\">THE PROJECT<\/p>\n<p data-path-to-node=\"7\">ScummVM has a number of engines that are almost finished \u2014 the games boot, most of the logic is there, but something keeps them from being shipped: incomplete low-level graphics, legacy code structures inherited from a decompilation, or gameplay bugs nobody has sat down and tracked to the end. My proposal listed several such candidates. My mentor&#8217;s guidance was clear and, in hindsight, exactly right: rather than touching many engines superficially, take two of them all the way to a releasable state.<\/p>\n<p data-path-to-node=\"8\">The two were:<\/p>\n<ul data-path-to-node=\"9\">\n<li>\n<p data-path-to-node=\"9,0,0\">Chamber of the Sci-Mutant Priestess \u2014 a 1989 adventure by Delphine Software, whose ScummVM engine had a working CGA path but a broken EGA one, no Amiga support, and a long tail of gameplay bugs.<\/p>\n<\/li>\n<li>\n<p data-path-to-node=\"9,1,0\">MacVenture \u2014 the engine behind D\u00e9j\u00e0 Vu, D\u00e9j\u00e0 Vu II, Shadowgate and Uninvited, which ran but crashed regularly and diverged from the original in ways that made the games unpleasant or impossible to finish.<\/p>\n<\/li>\n<\/ul>\n<p data-path-to-node=\"10\">One thing changed along the way. Chamber&#8217;s Amiga releases turned out to be a much larger and more interesting piece of work than anticipated \u2014 a whole second renderer, with planar graphics, a different palette system and two separate regional releases. I discussed it with my mentor and we agreed it was worth doing properly rather than skipping. It became roughly a third of the summer.<\/p>\n<p data-path-to-node=\"11\">WHAT I DID<\/p>\n<p data-path-to-node=\"12\">Chamber of the Sci-Mutant Priestess<\/p>\n<p data-path-to-node=\"13\">Getting EGA right. The EGA renderer was the headline problem. I fixed detection MD5s and title screen rendering, a transition that took twenty seconds on player death, mouse click coordinate latching, cursor hotspots, and implemented a missing script opcode. Later came a series of memory-layout bugs where EGA&#8217;s different buffer geometry caused writes to overflow into neighbouring structures and corrupt sprite lists and the backbuffer.<\/p>\n<p data-path-to-node=\"14\">Gameplay and scripting. An infinite &#8220;you failed the ordeals&#8221; death loop caused by a timer bleeding across rooms. An endgame confrontation menu that re-prompted forever because a priority command never restored its stack pointer. An opcode whose operand width was wrong by one byte, silently desynchronising the whole script stream after it. Stale actors and commands surviving room transitions.<\/p>\n<p data-path-to-node=\"15\">Randomness. The engine&#8217;s randomize() was a stub, so the seed was always zero and the sequence identical on every run \u2014 which made the same character spawn first in every single playthrough. The original seeded from the BIOS timer tick, and that seed is only the starting offset into a fixed table the game walks for its random values. I kept the table, so the distribution still matches DOS exactly, and took the offset from Common::RandomSource instead \u2014 which, on my mentor&#8217;s suggestion, also means the random_seed config key makes a run reproducible when you are chasing a bug.<\/p>\n<p data-path-to-node=\"16\">The Amiga port. This was the biggest single piece. I reverse-engineered the Amiga data formats \u2014 16-colour four-plane bitplanes, 12-bit RGB palettes, the SPRIT\/PUZZL sprite containers with their byte-swapped dimensions, the cursor format \u2014 and built a renderer that shares the EGA chunky pipeline while differing in palette and planar conversion. Then the same again for the US &#8220;Chamber&#8221; release, whose executable has a completely different static-resource offset table. Both the European &#8220;Kult&#8221; and US releases are now playable start to finish.<\/p>\n<p data-path-to-node=\"17\">Save\/load. Scripted room changes \u2014 the De Profundis monster, Deilos \u2014 lived only in the backbuffer and vanished when you reloaded. Version 2 of the save format stores the backbuffer.<\/p>\n<p data-path-to-node=\"18\">Release work. Static analysis passes (Coverity and PVS-Studio findings), a detection fix for folders containing both CGA and EGA data (bug 17004), engine enabled by default, all variants promoted to testing.<\/p>\n<p data-path-to-node=\"19\">MacVenture<\/p>\n<p data-path-to-node=\"20\">Getting the data in. The Steam re-releases wrap the game data in a CEF application, with an HFS disk image buried in a PE resource. I wrote a devtools extractor for it, extended it to the Apple IIGS disks, and fixed IIGS detection, which had been silently dead because there was no data-fork fallback.<\/p>\n<p data-path-to-node=\"21\">Crashes. Inventory windows closed out of order, a use-after-free where a window callback deleted its own data while the engine kept dispatching through the dangling pointer, an unsigned coordinate wrapping when you dragged an object off-screen, a double free in the CALL opcode when a script called a function that does not exist, a double delete in the text-input dialog. Plus one in shared MacGUI code, where past roughly 680 lines of scrollback the rectangle maths overflowed a 16-bit Common::Rect.<\/p>\n<p data-path-to-node=\"22\">Making it behave like the original. Inventory window placement and sizing, lasso selection picking the wrong objects, Clean Up throwing items outside their window, the watch cursor while a command is processed, &#8220;click to continue&#8221; console paging, dialog buttons that invert while held and only act on release, shift-clicking to select several objects at once, and the diploma at the end of D\u00e9j\u00e0 Vu actually being signed with the player&#8217;s name.<\/p>\n<p data-path-to-node=\"23\">Timing. The SLEEP opcode computed (ticks \/ 60) * 1000, truncating every sub-second pause to zero, so animations flew past. And the GUI was forcing a full-screen refresh every frame, running the game at 17 fps instead of 50.<\/p>\n<p data-path-to-node=\"24\">Two engine-level corrections. The random opcode returned a value inclusive of its maximum where the original returns one strictly below \u2014 every script indexing a table with it could read one past the end. And commands could not target the object they were invoked on, because a workaround for a duplicate-execution bug skipped the destination entirely; the real fix was to keep the destination out of the selection queue in the first place, as the original does.<\/p>\n<p data-path-to-node=\"25\">Shared ScummVM code<\/p>\n<p data-path-to-node=\"26\">Not everything was engine-local. Two fixes landed in shared code: an invalid-rectangle bug in the Mac GUI text renderer, a new absolute scrollTo() on MacTextWindow, and a SurfaceSDL regression that drew the game cursor several pixels off-target at scale factors above 1x \u2014 which affected every engine, not just mine.<\/p>\n<p data-path-to-node=\"27\">CURRENT STATE<\/p>\n<p data-path-to-node=\"28\">Chamber of the Sci-Mutant Priestess is enabled by default and all five variants are marked as testing. It is completable on CGA, EGA, Hercules, and on both the European and US Amiga releases. The Steam release is detected and playable.<\/p>\n<p data-path-to-node=\"29\">MacVenture is in review for the same treatment. D\u00e9j\u00e0 Vu is completable from start to finish. D\u00e9j\u00e0 Vu II has been played to within sight of the ending and every blocking bug I hit along the way is fixed; the last stretch of the playthrough is the one piece of testing I did not get to finish. The two pull requests that enable the engine by default and promote the Macintosh releases to testing are open at the time of writing.<\/p>\n<p data-path-to-node=\"30\">WEEKLY BREAKDOWN<\/p>\n<p data-path-to-node=\"31\">Every week of the coding period has a blog post describing the work in detail. The pull requests for each week are listed alongside.<\/p>\n<p data-path-to-node=\"32\">Week 1 &#8211; Focus: EGA detection, rendering and input; a rigged minigame and a frozen snake<\/p>\n<p data-path-to-node=\"32\">Post: <a class=\"ng-star-inserted\" href=\"https:\/\/blogs.scummvm.org\/andy\/2026\/05\/31\/week-1\/\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQigI\">Week 1<\/a> Pull request: <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7530\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQiwI\">7530<\/a><\/p>\n<p data-path-to-node=\"33\">Week 2 &#8211; Focus: RNG seeding, ordeal timer death loop, state leaking across rooms, opcode operand width<\/p>\n<p data-path-to-node=\"33\">Post: <a class=\"ng-star-inserted\" href=\"https:\/\/blogs.scummvm.org\/andy\/2026\/06\/08\/week-2\/\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQjAI\">Week 2<\/a> Pull request: <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7566\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQjQI\">7566<\/a><\/p>\n<p data-path-to-node=\"34\">Week 3 &#8211; Focus: Confrontation menu stack overflow, sprite assembly coordinates, EGA zone transitions<\/p>\n<p data-path-to-node=\"34\">Post: <a class=\"ng-star-inserted\" href=\"https:\/\/blogs.scummvm.org\/andy\/2026\/06\/15\/week-3\/\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQjgI\">Week 3<\/a> Pull request: <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7586\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQjwI\">7586<\/a><\/p>\n<p data-path-to-node=\"35\">Week 4 &#8211; Focus: EGA memory layout overflows, timer endianness, zone scan width<\/p>\n<p data-path-to-node=\"35\">Post: <a class=\"ng-star-inserted\" href=\"https:\/\/blogs.scummvm.org\/andy\/2026\/06\/22\/week-4\/\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQkAI\">Week 4<\/a> Pull request: <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7597\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQkQI\">7597<\/a><\/p>\n<p data-path-to-node=\"36\">Week 5 &#8211; Focus: Amiga EU renderer: palette, sprite banks, script padding \u2014 playable end to end<\/p>\n<p data-path-to-node=\"36\">Post: <a class=\"ng-star-inserted\" href=\"https:\/\/blogs.scummvm.org\/andy\/2026\/06\/29\/week-5\/\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQkgI\">Week 5<\/a> Pull request: <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7607\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQkwI\">7607<\/a><\/p>\n<p data-path-to-node=\"37\">Week 6 &#8211; Focus: Amiga US release support, detection entries, zone scan effect; SDL cursor hotspot fix<\/p>\n<p data-path-to-node=\"37\">Post: <a class=\"ng-star-inserted\" href=\"https:\/\/blogs.scummvm.org\/andy\/2026\/07\/06\/week-6\/\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQlAI\">Week 6<\/a> Pull requests: <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7629\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQlQI\">7629<\/a>, <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7628\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQlgI\">7628<\/a><\/p>\n<p data-path-to-node=\"38\">Week 7 &#8211; Focus: Coverity and PVS-Studio findings; save format v2 storing the backbuffer<\/p>\n<p data-path-to-node=\"38\">Post: <a class=\"ng-star-inserted\" href=\"https:\/\/blogs.scummvm.org\/andy\/2026\/07\/13\/week-7\/\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQlwI\">Week 7<\/a> Pull request: <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7629\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQmAI\">7629<\/a><\/p>\n<p data-path-to-node=\"39\">Week 8 &#8211; Focus: Chamber enabled for release and promoted to testing; first look at MacVenture<\/p>\n<p data-path-to-node=\"39\">Post: <a class=\"ng-star-inserted\" href=\"https:\/\/blogs.scummvm.org\/andy\/2026\/07\/20\/week-8\/\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQmQI\">Week 8<\/a> Pull request: <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7705\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQmgI\">7705<\/a><\/p>\n<p data-path-to-node=\"40\">Week 9 &#8211; Focus: Steam and IIGS extraction tooling, IIGS detection, an uninitialised field causing assertions<\/p>\n<p data-path-to-node=\"40\">Post: <a class=\"ng-star-inserted\" href=\"https:\/\/blogs.scummvm.org\/andy\/2026\/07\/27\/week-9\/\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQmwI\">Week 9<\/a> Pull requests: <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7722\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQnAI\">7722<\/a>, <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7726\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQnQI\">7726<\/a>, <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7728\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQngI\">7728<\/a>, <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7748\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQnwI\">7748<\/a><\/p>\n<p data-path-to-node=\"41\">Week 10 &#8211; Focus: Playing D\u00e9j\u00e0 Vu through: Clean Up coordinates, console scrolling, watch cursor, animation pacing<\/p>\n<p data-path-to-node=\"41\">Post: <a class=\"ng-star-inserted\" href=\"https:\/\/blogs.scummvm.org\/andy\/2026\/08\/03\/week-10\/\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQoAI\">Week 10<\/a> Pull request: <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7760\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQoQI\">7760<\/a><\/p>\n<p data-path-to-node=\"42\">Week 11 &#8211; Focus: Inventory crashes, lasso selection, 17\u219250 fps, the signed diploma, click to continue<\/p>\n<p data-path-to-node=\"42\">Post: <a class=\"ng-star-inserted\" href=\"https:\/\/blogs.scummvm.org\/andy\/2026\/08\/10\/week-11\/\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQogI\">Week 11<\/a> Pull requests: <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7773\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQowI\">7773<\/a>, <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7784\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQpAI\">7784<\/a>, <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7787\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQpQI\">7787<\/a>, <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7807\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQpgI\">7807<\/a><\/p>\n<p data-path-to-node=\"43\">Week 12 &#8211; Focus: D\u00e9j\u00e0 Vu II: script crashes, operate-on-itself, shift click, dialog buttons; release packaging<\/p>\n<p data-path-to-node=\"43\">Post: <a class=\"ng-star-inserted\" href=\"https:\/\/blogs.scummvm.org\/andy\/2026\/08\/17\/week-12\/\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQpwI\">Week 12<\/a> Pull requests: <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7820\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQqAI\">7820<\/a>, <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7830\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQqQI\">7830<\/a>, <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7834\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQqgI\">7834<\/a><\/p>\n<p data-path-to-node=\"44\">All pull requests are merged except <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7830\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQqwI\">7830<\/a> and <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7834\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQrAI\">7834<\/a>, which are open and awaiting review.<\/p>\n<p data-path-to-node=\"45\">WHAT IS LEFT TO DO<\/p>\n<p data-path-to-node=\"46\">I would rather be honest about this than leave someone guessing.<\/p>\n<p data-path-to-node=\"47\">In review. <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7830\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQrQI\">7830<\/a> (enable MacVenture by default, add credits) and <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7834\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQrgI\">7834<\/a> (promote the Macintosh releases to testing) are open. They are the last step before MacVenture can ship.<\/p>\n<p data-path-to-node=\"48\">Finish the D\u00e9j\u00e0 Vu II playthrough. I got very close to the ending, and the run was clean by that point, but the final stretch has not been played. It is a short job and the obvious first thing for anyone continuing this work.<\/p>\n<p data-path-to-node=\"49\">Click to continue needs polish. The console now pauses and pages through long messages the way the original does, and it works \u2014 but the interaction is not yet as smooth as the real thing in every situation. It is functional, not finished.<\/p>\n<p data-path-to-node=\"50\">Five sounds in D\u00e9j\u00e0 Vu II do not play. Fifteen of the twenty work. The remaining five are not audio data at all: they are 68k CODE resources that the original played by executing them. Supporting them needs actual 68k emulation, which is well outside the scope of a bug fix.<\/p>\n<p data-path-to-node=\"51\">Drawing mid-script is unsafe. MacVenture only assembles a fully consistent screen at the end of its main loop. Any attempt to draw from inside a running script (the opdeUPSC path) trips over half-built windows and invalid rectangles. I worked around it by pacing the main loop on elapsed time, which fixed the animations I needed, but the proper fix is a real animation path through the engine&#8217;s update cycle. Anyone attempting it should expect the crashes I did.<\/p>\n<p data-path-to-node=\"52\">WindowData::bounds mixes coordinate systems. It holds content coordinates in some places and screen coordinates in others. I left this deliberately: updateWindow&#8217;s fillRect and the &#8220;mess up&#8221; logic both depend on the current behaviour, and untangling it safely is a refactor of its own rather than something to slip into a bug-fix branch. It is the single biggest source of coordinate confusion in the engine and worth doing properly.<\/p>\n<p data-path-to-node=\"53\">Shadowgate and Uninvited need a full playthrough. MacVenture supports four games. I gave both of these a short look \u2014 they start up and play fine as far as I took them \u2014 but neither has had the sit-down-and-finish-it treatment that D\u00e9j\u00e0 Vu and D\u00e9j\u00e0 Vu II got. Given how much that turned up in the other two, I would expect a similar list from each.<\/p>\n<p data-path-to-node=\"54\">Chamber has no per-language text support. The engine only distinguishes English (EN_USA) from non-English, so the French and German releases cannot be presented properly. Adding real per-language handling needs engine work, not just detection entries.<\/p>\n<p data-path-to-node=\"55\">CHALLENGES AND LESSONS LEARNED<\/p>\n<p data-path-to-node=\"56\">Coordinate systems were the theme of the summer. Clean Up throwing items out of their windows, lasso selection grabbing the wrong objects, inventory windows cascading off the bottom of the screen, the SDL cursor drawn several pixels off \u2014 all the same class of bug. What finally made the lasso one fall into place was not a clever insight, it was writing down explicitly which system each value was in: the mouse event is relative to the outer window, objects are relative to the content area plus scroll position. Once that was on paper the fix was obvious. I now do this first rather than last.<\/p>\n<p data-path-to-node=\"57\">Reverse engineering without ground truth is slow, and you should go get ground truth. I spent a long time on the Amiga sprite bank encoding, trying chunky and every planar layout I could think of, and getting noise every time. The productive move \u2014 which I got to later than I should have \u2014 was to stop guessing at the format and go look at what the original executable actually does. Guessing scales badly; disassembly does not.<\/p>\n<p data-path-to-node=\"58\">Old workarounds hide real bugs. My favourite fix of the summer was the D\u00e9j\u00e0 Vu II flashlight doing nothing when you operated it. The cause was a workaround someone had added for a duplicate-execution bug: skip the destination while running the selection queue. It stopped the duplicate and also broke every command whose target is its own source. The lesson is that when a workaround produces a second symptom, the workaround is usually the thing to remove, not to extend.<\/p>\n<p data-path-to-node=\"59\">Playing the game is the best bug report you can write. Weeks 10 through 12 were the most productive of the summer, and all I did was sit down and actually play the games with a notebook. Every bug I fixed in that stretch came from noticing something felt wrong, not from reading code \u2014 the same way I had found most of Chamber&#8217;s.<\/p>\n<p data-path-to-node=\"60\">Check your build flags before you blame the engine. I lost time chasing jerky, stuttering gameplay that turned out to be a build configured with &#8211;enable-debug and no optimisations at all. The engine was fine.<\/p>\n<p data-path-to-node=\"61\">Static analysis is worth a dedicated pass. Handing Coverity and PVS-Studio output a full afternoon surfaced real dead stores, leaks and uninitialised reads that no amount of playing would have found.<\/p>\n<p data-path-to-node=\"62\">PRIOR CONTRIBUTIONS<\/p>\n<p data-path-to-node=\"63\">For completeness, and to be clear about what belongs to the GSoC period and what does not: I was contributing to Chamber before the coding period began on 25 May. These pull requests are not part of my GSoC work, but they are the foundation the summer built on.<\/p>\n<p data-path-to-node=\"64\"><a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7267\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQrwI\">7267<\/a> \u00b7 <a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7270\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQsAI\">7270<\/a> \u2014 splash screen refactor and Hercules palettes moved to the global graphics manager<\/p>\n<p data-path-to-node=\"64\"><a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7294\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQsQI\">7294<\/a> \u2014 Hercules scaling<\/p>\n<p data-path-to-node=\"64\"><a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7440\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQsgI\">7440<\/a> \u2014 initial EGA rendering<\/p>\n<p data-path-to-node=\"64\"><a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7474\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQswI\">7474<\/a> \u2014 save\/load support<\/p>\n<p data-path-to-node=\"64\"><a class=\"ng-star-inserted\" href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7479\" target=\"_blank\" rel=\"noopener\" data-hveid=\"0\" data-ved=\"0CAAQ_4QMahgKEwj36_SH0qeWAxUAAAAAHQAAAAAQtAI\">7479<\/a> \u2014 splash screen filenames moved to detection flags<\/p>\n<p data-path-to-node=\"65\">ACKNOWLEDGEMENTS<\/p>\n<p data-path-to-node=\"66\">Thank you to my mentors, especially sev, for twelve weeks of steady guidance, quick reviews and genuine patience \u2014 including the times I turned up with a coordinate bug I had already been warned about. Thank you also to the wider ScummVM community for the review comments, and to Google for running the program.<\/p>\n<p data-path-to-node=\"67\">Twelve weeks ago I had never touched either of these engines. Both are now heading for a release. That still feels slightly unreal.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>GSoC 2026 Final Report \u2014 Finishing Incomplete ScummVM Engines Contributor: Ion Andrei Cristian \u00b7 Organization: ScummVM \u00b7 Coding period: 25 May \u2013 17 August 2026 This is my final work product for Google Summer of Code 2026. It collects everything I worked on this summer in one place: what the project set out to do, [&hellip;]<\/p>\n","protected":false},"author":31,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-105","post","type-post","status-publish","format-standard","hentry","category-gsoc-2026"],"_links":{"self":[{"href":"https:\/\/blogs.scummvm.org\/andy\/wp-json\/wp\/v2\/posts\/105","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.scummvm.org\/andy\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.scummvm.org\/andy\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.scummvm.org\/andy\/wp-json\/wp\/v2\/users\/31"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.scummvm.org\/andy\/wp-json\/wp\/v2\/comments?post=105"}],"version-history":[{"count":6,"href":"https:\/\/blogs.scummvm.org\/andy\/wp-json\/wp\/v2\/posts\/105\/revisions"}],"predecessor-version":[{"id":111,"href":"https:\/\/blogs.scummvm.org\/andy\/wp-json\/wp\/v2\/posts\/105\/revisions\/111"}],"wp:attachment":[{"href":"https:\/\/blogs.scummvm.org\/andy\/wp-json\/wp\/v2\/media?parent=105"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.scummvm.org\/andy\/wp-json\/wp\/v2\/categories?post=105"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.scummvm.org\/andy\/wp-json\/wp\/v2\/tags?post=105"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}