{"id":67,"date":"2025-07-22T02:39:13","date_gmt":"2025-07-22T02:39:13","guid":{"rendered":"https:\/\/blogs.scummvm.org\/prime\/?p=67"},"modified":"2025-07-22T02:39:13","modified_gmt":"2025-07-22T02:39:13","slug":"week-7-sherlock-engine-keymapper","status":"publish","type":"post","link":"https:\/\/blogs.scummvm.org\/prime\/2025\/07\/22\/week-7-sherlock-engine-keymapper\/","title":{"rendered":"Week 7: Sherlock Engine Keymapper"},"content":{"rendered":"<p data-start=\"163\" data-end=\"450\">This week was a major milestone: I passed my <strong data-start=\"208\" data-end=\"231\">midterm evaluations<\/strong>! \ud83c\udf89 Right after that, I dove straight into one of the most complex engines so far\u2014<strong data-start=\"323\" data-end=\"367\">the Sherlock engine<\/strong>. I also got my <a href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/6793\"><strong data-start=\"383\" data-end=\"393\">Buried<\/strong><\/a> and <a href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/6797\"><strong data-start=\"398\" data-end=\"408\">Access<\/strong><\/a> keymapper PRs merged earlier in the week.<\/p>\n<h4 data-start=\"452\" data-end=\"472\">Sherlock Engine<\/h4>\n<p data-start=\"474\" data-end=\"563\">The Sherlock engine supports two games from <em data-start=\"518\" data-end=\"553\">The Lost Files of Sherlock Holmes<\/em> series:<\/p>\n<ul>\n<li data-start=\"566\" data-end=\"602\"><em data-start=\"566\" data-end=\"600\">The Case of the Serrated Scalpel<\/em><\/li>\n<li data-start=\"605\" data-end=\"634\"><em data-start=\"605\" data-end=\"634\">The Case of the Rose Tattoo<\/em><\/li>\n<\/ul>\n<p data-start=\"636\" data-end=\"949\">This engine was <strong data-start=\"652\" data-end=\"679\">by far the most complex<\/strong> I\u2019ve worked on, with around <strong data-start=\"708\" data-end=\"745\">2000 insertions and 600 deletions<\/strong>. Both games have <strong data-start=\"763\" data-end=\"795\">separate input handling code<\/strong>, yet they share some common code. This made changes particularly delicate\u2014I had to make sure that updating one game\u2019s behavior wouldn\u2019t break the other.<\/p>\n<h5 data-start=\"951\" data-end=\"989\">The Case of the Serrated Scalpel<\/h5>\n<p data-start=\"991\" data-end=\"1246\">This game turned out to be the trickiest, mainly because it\u2019s <strong data-start=\"1053\" data-end=\"1091\">localized in 5 different languages<\/strong>. Each language has its own translated UI, including verbs like \u201cLook\u201d or \u201cTalk\u201d.<\/p>\n<p data-start=\"1248\" data-end=\"1593\">Why does this matter?<br data-start=\"1269\" data-end=\"1272\" \/>The game uses the <strong data-start=\"1290\" data-end=\"1330\">first letter of a verb\/option to trigger it<\/strong> via keyboard shortcuts. For example, \u201cL\u201d for \u201cLook\u201d (or its translated equivalent). Thankfully, the engine code already had these localized key bindings stored. I leveraged that to bind the correct keys to actions dynamically, based on the game\u2019s language.<\/p>\n<p data-start=\"1595\" data-end=\"1922\">Another subtle challenge was visual feedback: when a verb is selected, the corresponding UI button appears pressed. If the player selects a different verb or deselects the current one, the button should visually \u201cpop back out.\u201d Implementing this required extra logic to track which verb is active and update the UI accordingly.<\/p>\n<p data-start=\"1924\" data-end=\"2009\">Also, the sheer <strong data-start=\"1940\" data-end=\"1970\">number of possible actions<\/strong> took significant time to map properly.<\/p>\n<h5 data-start=\"2011\" data-end=\"2044\">The Case of the Rose Tattoo<\/h5>\n<p data-start=\"2046\" data-end=\"2186\">Compared to Scalpel, this one had a slightly easier path since it&#8217;s <strong data-start=\"2114\" data-end=\"2131\">not localized<\/strong>. Hence no need to worry about language-specific keybindings.<\/p>\n<p data-start=\"2188\" data-end=\"2382\">However, it still had <strong data-start=\"2210\" data-end=\"2232\">more total actions<\/strong>, which made the task just as time-consuming. The logic was a bit cleaner here, so once the actions were identified, the process went fairly smoothly.<\/p>\n<hr data-start=\"2384\" data-end=\"2387\" \/>\n<h3 data-start=\"2389\" data-end=\"2400\">Wrap-Up<\/h3>\n<p data-start=\"2402\" data-end=\"2415\">This week, I:<\/p>\n<ul>\n<li data-start=\"2419\" data-end=\"2457\">Passed my <strong data-start=\"2429\" data-end=\"2452\">midterm evaluations<\/strong> \ud83c\udf89<\/li>\n<li>Got my <a href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/6793\"><strong data-start=\"2467\" data-end=\"2477\">Buried<\/strong><\/a> and <a href=\"https:\/\/github.com\/scummvm\/scummvm\/pull\/6797\"><strong data-start=\"2482\" data-end=\"2492\">Access<\/strong><\/a> keymapper PRs merged\ud83c\udf89<\/li>\n<li data-start=\"2518\" data-end=\"2620\">Implemented <strong data-start=\"2530\" data-end=\"2575\">keymapper support for the Sherlock engine<\/strong><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>This week was a major milestone: I passed my midterm evaluations! \ud83c\udf89 Right after that, I dove straight into one of the most complex engines so far\u2014the Sherlock engine. I also got my Buried and Access keymapper PRs merged earlier in the week. Sherlock Engine The Sherlock engine supports two games from The Lost Files [&hellip;]<\/p>\n","protected":false},"author":28,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10],"tags":[],"class_list":["post-67","post","type-post","status-publish","format-standard","hentry","category-week-7"],"_links":{"self":[{"href":"https:\/\/blogs.scummvm.org\/prime\/wp-json\/wp\/v2\/posts\/67","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.scummvm.org\/prime\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.scummvm.org\/prime\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.scummvm.org\/prime\/wp-json\/wp\/v2\/users\/28"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.scummvm.org\/prime\/wp-json\/wp\/v2\/comments?post=67"}],"version-history":[{"count":3,"href":"https:\/\/blogs.scummvm.org\/prime\/wp-json\/wp\/v2\/posts\/67\/revisions"}],"predecessor-version":[{"id":70,"href":"https:\/\/blogs.scummvm.org\/prime\/wp-json\/wp\/v2\/posts\/67\/revisions\/70"}],"wp:attachment":[{"href":"https:\/\/blogs.scummvm.org\/prime\/wp-json\/wp\/v2\/media?parent=67"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.scummvm.org\/prime\/wp-json\/wp\/v2\/categories?post=67"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.scummvm.org\/prime\/wp-json\/wp\/v2\/tags?post=67"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}