{"id":300,"date":"2026-07-07T16:50:06","date_gmt":"2026-07-07T16:50:06","guid":{"rendered":"https:\/\/blogs.scummvm.org\/mohit\/?p=300"},"modified":"2026-07-07T17:33:26","modified_gmt":"2026-07-07T17:33:26","slug":"closing-the-dungeon-gates","status":"publish","type":"post","link":"https:\/\/blogs.scummvm.org\/mohit\/2026\/07\/07\/closing-the-dungeon-gates\/","title":{"rendered":"Closing the Dungeon Gates"},"content":{"rendered":"<p>Hello and welcome back! This is Week 6 of my GSoC journey, and\u00a0I&#8217;m excited to share that I&#8217;ve finally <strong>completed the Dungeon Master engine!<\/strong><\/p>\n<h4 class=\"text-text-100 mt-2 -mb-1 text-base font-bold\"><span style=\"color: #993300\">Fixing the Endianness Problem<\/span><\/h4>\n<p>As I mentioned in the last blog, using <code class=\"bg-text-200\/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]\">READ_LE_UINT16<\/code> and <code class=\"bg-text-200\/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]\">WRITE_LE_UINT16<\/code> macros had a deeper issue \u2014 <code class=\"bg-text-200\/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]\">loadDungeonFile()<\/code> reads Big-Endian file data and stores it into <code class=\"bg-text-200\/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]\">_thingData<\/code> as native-endian <code class=\"bg-text-200\/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]\">uint16s<\/code>, so on a Big-Endian machine the whole setup breaks regardless of the macro fix.<\/p>\n<p>So I spent the first half of this week replacing those byte offset macros by parsing the file data directly into respective arrays of structs at load time. This involved removing all raw byte-to-struct pointer casting (e.g., <code class=\"bg-text-200\/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]\">(Door *)rawDat<\/code>) from the codebase and updating the file loading and saving routines to read and write fields one at a time using stream operations like <code class=\"bg-text-200\/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]\">readUint16BE<\/code> and <code class=\"bg-text-200\/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]\">writeUint16BE<\/code>.<\/p>\n<h4 class=\"text-text-100 mt-2 -mb-1 text-base font-bold\"><span style=\"color: #993300\">Uncovering Hidden Bugs<\/span><\/h4>\n<p class=\"font-claude-response-body break-words whitespace-normal\">These changes also brought some new freezes and crashes to the surface \u2014 bugs that were silently hiding behind the old unsafe code. Raw pointer arithmetic was allowing silent reads and writes to out-of-bounds memory, which switching to <code class=\"bg-text-200\/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]\">Common::Array<\/code> now catches immediately as crashes or assertions. Unsafe casting was hiding cases where one object type was being read as another, which strict C++ type assertions now catch instantly.<\/p>\n<h4><span style=\"color: #993300\">Debugging the\u00a0Endgame<\/span><\/h4>\n<p>The endgame sequence had quite a few bugs hiding in it. When you capture the Lord of Chaos and fuse him with The Firestaff, the game unlinks the fluxcage \u2014 but in <code class=\"bg-text-200\/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]\">fuseSequence()<\/code>, <code class=\"bg-text-200\/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]\">curThing<\/code> was never being reset after that, causing the loop to run forever.<\/p>\n<p>When the Lord of Chaos was turned back to normal, the message displayed was also corrupted \u2014 <code class=\"bg-text-200\/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]\">wrkString<\/code> was declared outside the loop so it kept accumulating characters from previous words, and a stray <code class=\"bg-text-200\/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]\">\\0<\/code> append was preventing it from reading past the first word. Moving <code class=\"bg-text-200\/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]\">wrkString<\/code> inside the loop and removing <code>\\0<\/code> fixed the issue.<\/p>\n<p>Another text bug had only the second row showing up in the message area \u2014 the first row was being cleared before it could scroll up. <code class=\"bg-text-200\/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]\">createNewRow()<\/code> was clearing the line buffer before the scroll animation could finish, so the fix was to wait in a small delay loop until <code class=\"bg-text-200\/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]\">_isScrolling<\/code> is false before proceeding.<\/p>\n<p>Beyond that, I also added support for returning to the launcher after closing the game, along with other small fixes to get the engine to a solid, playable state.<\/p>\n<h4><span style=\"color: #993300\">Crash When Renaming Champion in the Hall of Champions<\/span><\/h4>\n<p>Clicking outside the character select table during champion renaming was calculating an invalid character index from out-of-bounds coordinates, causing a crash. The fix was straightforward \u2014 enabling a bounds check that was previously disabled, so clicks outside the table are now simply ignored.<\/p>\n<h4 class=\"text-text-100 mt-2 -mb-1 text-base font-bold\"><span style=\"color: #993300\">Implementing Extended Saves<\/span><\/h4>\n<p class=\"font-claude-response-body break-words whitespace-normal\">I also implemented extended saves for the DM engine, allowing the game to make use of ScummVM&#8217;s extended save functionality.<\/p>\n<p class=\"font-claude-response-body break-words whitespace-normal\">That was it for this week! It&#8217;s been a long road getting the DM engine to this point, but it&#8217;s rewarding to finally see the work of the previous contributor and Strangerke pay off after 10 years. You can find the previous contributor&#8217;s blog <a href=\"https:\/\/blogs.scummvm.org\/wintergrascph\/\">here<\/a>.<\/p>\n<p>Thanks to Sev for helping me throughout this.<\/p>\n<p>I&#8217;ll see you in the next blog as I dive into a new engine. Until then, bye! \ud83d\udc4b<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hello and welcome back! This is Week 6 of my GSoC journey, and\u00a0I&#8217;m excited to share that I&#8217;ve finally completed the Dungeon Master engine! Fixing the Endianness Problem As I mentioned in the last blog, using READ_LE_UINT16 and WRITE_LE_UINT16 macros had a deeper issue \u2014 loadDungeonFile() reads Big-Endian file data and stores it into _thingData [&hellip;]<\/p>\n","protected":false},"author":30,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10],"tags":[],"class_list":["post-300","post","type-post","status-publish","format-standard","hentry","category-week-6"],"_links":{"self":[{"href":"https:\/\/blogs.scummvm.org\/mohit\/wp-json\/wp\/v2\/posts\/300","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.scummvm.org\/mohit\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.scummvm.org\/mohit\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.scummvm.org\/mohit\/wp-json\/wp\/v2\/users\/30"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.scummvm.org\/mohit\/wp-json\/wp\/v2\/comments?post=300"}],"version-history":[{"count":20,"href":"https:\/\/blogs.scummvm.org\/mohit\/wp-json\/wp\/v2\/posts\/300\/revisions"}],"predecessor-version":[{"id":320,"href":"https:\/\/blogs.scummvm.org\/mohit\/wp-json\/wp\/v2\/posts\/300\/revisions\/320"}],"wp:attachment":[{"href":"https:\/\/blogs.scummvm.org\/mohit\/wp-json\/wp\/v2\/media?parent=300"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.scummvm.org\/mohit\/wp-json\/wp\/v2\/categories?post=300"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.scummvm.org\/mohit\/wp-json\/wp\/v2\/tags?post=300"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}