{"id":76,"date":"2026-06-30T18:27:54","date_gmt":"2026-06-30T18:27:54","guid":{"rendered":"https:\/\/blogs.scummvm.org\/ramyak\/?p=76"},"modified":"2026-06-30T18:29:35","modified_gmt":"2026-06-30T18:29:35","slug":"76","status":"publish","type":"post","link":"https:\/\/blogs.scummvm.org\/ramyak\/2026\/06\/30\/76\/","title":{"rendered":"Fixing Scripts, Text, and Finding Gus"},"content":{"rendered":"<p>This week had a mix of bug fixes, debugger improvements, and game detection work. Let me walk through what happened.<\/p>\n<p>Before I get into bugs, a quick note: I will be posting a separate blog on the visual debugger soon. Here is a snippet from a data flow diagram for the dt:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-77\" src=\"https:\/\/blogs.scummvm.org\/ramyak\/wp-content\/uploads\/sites\/84\/2026\/06\/DT-scaled.png\" alt=\"\" width=\"2560\" height=\"1671\" srcset=\"https:\/\/blogs.scummvm.org\/ramyak\/wp-content\/uploads\/sites\/84\/2026\/06\/DT-scaled.png 2560w, https:\/\/blogs.scummvm.org\/ramyak\/wp-content\/uploads\/sites\/84\/2026\/06\/DT-300x196.png 300w, https:\/\/blogs.scummvm.org\/ramyak\/wp-content\/uploads\/sites\/84\/2026\/06\/DT-1024x668.png 1024w, https:\/\/blogs.scummvm.org\/ramyak\/wp-content\/uploads\/sites\/84\/2026\/06\/DT-768x501.png 768w, https:\/\/blogs.scummvm.org\/ramyak\/wp-content\/uploads\/sites\/84\/2026\/06\/DT-1536x1003.png 1536w, https:\/\/blogs.scummvm.org\/ramyak\/wp-content\/uploads\/sites\/84\/2026\/06\/DT-2048x1337.png 2048w, https:\/\/blogs.scummvm.org\/ramyak\/wp-content\/uploads\/sites\/84\/2026\/06\/DT-1200x783.png 1200w, https:\/\/blogs.scummvm.org\/ramyak\/wp-content\/uploads\/sites\/84\/2026\/06\/DT-1980x1293.png 1980w\" sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" \/><\/p>\n<p><strong>An Unresolved Bug<\/strong><\/p>\n<p>While testing Gus Goes to Cybertown&#8217;s Science Dome, I found a bug in the Sink or Float minigame: dropping the golf ball or spoon shows Prof. Gus&#8217; face instead of the drop animation.<\/p>\n<p>I traced it to <strong>cast member 525<\/strong> (s_fqt, a digital video) on channel 14, which spans <strong>frames 7350 &#8211; 7359<\/strong> during the drop animation.<\/p>\n<p>In the original Director 4, this sprite is effectively invisible, its bounding box appears as three vertical dots on stage, not selectable or resizable. For the spoon case, no bounding box appears at all. ScummVM renders it at full size (240\u00d7180) instead.<\/p>\n<p>The score stores the correct dimensions, setCast is called correctly, and the bbox passed to <code>createWidget<\/code> is right. So ScummVM is reading the data correctly &#8211; the original Director is doing something to suppress this sprite that we aren&#8217;t replicating yet. The likely culprits are the ink mode or a puppet flag, but I haven&#8217;t confirmed which yet.<\/p>\n<p>Sev&#8217;s advice was to study the score at the exact frame where the original renders correctly; check ink, dimensions, and puppet flag,\u00a0 and look for any Lingo touching that channel. If the cause still isn&#8217;t clear, the plan is to strip the movie down to just the affected frames and cast members as a minimal test case, which can then live in the test suite to prevent future regressions.<\/p>\n<p>This one is staying open for now. Sev also pointed out that since this bug is complicated, it&#8217;s worth finishing a sweep of all the Gus games first to find something simpler to close out, which is the plan for the coming week.<\/p>\n<p><strong>Text Wrapping\u00a0<\/strong><\/p>\n<p>The next bug I tackled was text wrapping in D4 text cast members. Some labels like &#8220;Hamburger&#8221; were incorrectly wrapping as &#8220;Hamburge\\nr&#8221;, one character too early.<\/p>\n<p>The root cause turned out to be two separate issues. MacText treats <code>maxWidth<\/code> as the outer width and subtracts border, gutter, and shadow internally, so I was passing the wrong value and the effective inner wrap width was narrower than the cast member&#8217;s designed text area.<\/p>\n<p>On top of that, <code>wordWrapTextImpl<\/code> was using <code>&gt;<\/code> instead of <code>&gt;=<\/code>, meaning text that exactly fills the available width was being wrapped onto a new line when it shouldn&#8217;t be.<\/p>\n<p>Both are easy fixes in isolation, but finding them required understanding how the text layout pipeline chains together across three layers. The fix ships with a regression test in director-tests.<\/p>\n<p><strong>Debugger (DT): Script Viewer<\/strong><\/p>\n<p>While testing Gus Goes to Cybertown, clicking on some cast members in the Cast window showed the script tooltip on hover but opened nothing on click. The script viewer window stayed empty.<\/p>\n<p>The issue has two parts. First, scripts using internal generic event handlers (<code>scummvm_generic<\/code>) were failing because <code>getHandler()<\/code> matched by <code>handler.name == handlerId<\/code> exactly, but generic event handlers store an empty name and are only identified by the <code>isGenericEvent<\/code> flag.<\/p>\n<p>Matching on that flag when handlerId is &#8220;<code>scummvm_generic<\/code>&#8221; fixes it.<\/p>\n<p>Second, some cast members return null from <code>getScriptContext()<\/code>, the root cause is still under investigation, but the scripts do exist and their source text is available in <code>CastMemberInfo::script<\/code>.<\/p>\n<p>As a workaround, <code>addToOpenHandlers()<\/code> now falls back to displaying the raw Lingo source text when no compiled AST is available.<\/p>\n<p>Sev shared a different D8 movie that had the same issue, which confirmed it&#8217;s not game-specific. The workaround covers that case too.<\/p>\n<p><strong>Gus Goes to Cybertown: Detection Entries<\/strong><\/p>\n<p>Gus Goes to Cybertown has three distinct Windows versions: Retail (Director 3), Retail Revised (Director 4), and Golden Master (Director 4). Each has different file sizes and hashes, so three separate detection entries were needed.<\/p>\n<p>That was a summary of most of the things I did this week.<\/p>\n<p>My next immediate goal is to fix the remaining gustown errors, and add it to release.<\/p>\n<p>PRs this week:<br \/>\n<a href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7598\">Fix text wrapping in D4 text cast members<\/a><br \/>\n<a href=\"https:\/\/github.com\/scummvm\/director-tests\/pull\/4\">D4-win director-tests repo changes for the above PR<\/a><br \/>\n<a href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7612\">Fix script not rendering in script viewer<\/a><br \/>\n<a href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/7614\">Add detection entries for Gus Goes to Cybertown<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This week had a mix of bug fixes, debugger improvements, and game detection work. Let me walk through what happened. Before I get into bugs, a quick note: I will be posting a separate blog on the visual debugger soon. Here is a snippet from a data flow diagram for the dt: An Unresolved Bug [&hellip;]<\/p>\n","protected":false},"author":32,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[],"class_list":["post-76","post","type-post","status-publish","format-standard","hentry","category-week-5"],"_links":{"self":[{"href":"https:\/\/blogs.scummvm.org\/ramyak\/wp-json\/wp\/v2\/posts\/76","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.scummvm.org\/ramyak\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.scummvm.org\/ramyak\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.scummvm.org\/ramyak\/wp-json\/wp\/v2\/users\/32"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.scummvm.org\/ramyak\/wp-json\/wp\/v2\/comments?post=76"}],"version-history":[{"count":3,"href":"https:\/\/blogs.scummvm.org\/ramyak\/wp-json\/wp\/v2\/posts\/76\/revisions"}],"predecessor-version":[{"id":80,"href":"https:\/\/blogs.scummvm.org\/ramyak\/wp-json\/wp\/v2\/posts\/76\/revisions\/80"}],"wp:attachment":[{"href":"https:\/\/blogs.scummvm.org\/ramyak\/wp-json\/wp\/v2\/media?parent=76"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.scummvm.org\/ramyak\/wp-json\/wp\/v2\/categories?post=76"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.scummvm.org\/ramyak\/wp-json\/wp\/v2\/tags?post=76"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}