{"id":28,"date":"2019-06-24T09:47:21","date_gmt":"2019-06-24T09:47:21","guid":{"rendered":"https:\/\/blogs.scummvm.org\/nipungarg\/?p=28"},"modified":"2022-05-22T09:51:31","modified_gmt":"2022-05-22T09:51:31","slug":"gsoc-update-week-4","status":"publish","type":"post","link":"https:\/\/blogs.scummvm.org\/nipungarg\/2019\/06\/24\/gsoc-update-week-4\/","title":{"rendered":"GSOC Update: Week 4"},"content":{"rendered":"<p>It\u2019s been a long week, and I had to implement two whole sub-systems during this time: AI and Window. Both of them are currently a work in progress, but they have produced tangible results on screen. Building out these two systems, I have faced a fair share of problems which will be discussed below. This will be a fairly long read.<\/p>\n<h3 id=\"map\">Map<\/h3>\n<p>In my last update that was two weeks ago, I had partially drawn the first level. I\u2019m glad to say that now I can draw the complete, as one can see below.<\/p>\n<p><em>(Editor&#8217;s notice: Unfortunately, the image\/video that was previously integrated here is lost and not archived)<\/em><\/p>\n<p>As you can see, I can now:<\/p>\n<ol>\n<li>Completely Background, Foreground and Grating tiles<\/li>\n<li>Scroll the map<\/li>\n<li>Initiate Dialog messages<\/li>\n<\/ol>\n<h3 id=\"ai\">AI<\/h3>\n<p>By far, the AI subsystem has been the biggest subsystem I have encountered so far. With multiple Struct types, constant data and member functions, it defines not only how the characters in the game behave, but also Animation and Drawing code for all of them.<\/p>\n<p>In a nutshell, this is how the AI subsystem works: Each object in the game that is more than just a drawn image is represented by the <code class=\"language-plaintext highlighter-rouge\">AIEntity<\/code> struct. The definition for this struct can be seen below:<\/p>\n<p><a href=\"https:\/\/blogs.scummvm.org\/nipungarg\/wp-content\/uploads\/sites\/28\/2019\/06\/AIEntity.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-30\" src=\"https:\/\/blogs.scummvm.org\/nipungarg\/wp-content\/uploads\/sites\/28\/2019\/06\/AIEntity.png\" alt=\"\" width=\"883\" height=\"897\" srcset=\"https:\/\/blogs.scummvm.org\/nipungarg\/wp-content\/uploads\/sites\/28\/2019\/06\/AIEntity.png 883w, https:\/\/blogs.scummvm.org\/nipungarg\/wp-content\/uploads\/sites\/28\/2019\/06\/AIEntity-295x300.png 295w, https:\/\/blogs.scummvm.org\/nipungarg\/wp-content\/uploads\/sites\/28\/2019\/06\/AIEntity-768x780.png 768w\" sizes=\"auto, (max-width: 883px) 100vw, 883px\" \/><\/a>As you can see, it contains Enums for defining Entity Type, State, Direction, Entity position, velocity as well as range of function pointers for Initialization, Drawing and possible Actions. A major portion of the AI subsystem is dedicated towards manipulating Entities of the type AIEntity.<\/p>\n<p>The AI subsystem also maintains a series of lists for processing different events such as Actions, AutoActions etc.<\/p>\n<h3 id=\"cinematic-system\">Cinematic System<\/h3>\n<p>While it is a part of the AI subsystem, I believe it deserves a separate mention. Basically, the Cinematic System is designed to run scripted interactions between Entities &#8211; the HDB equivalent cutscenes in a way.<\/p>\n<p>Here\u2019s how it works: The Cinematic System is a giant state machine that manages a queue of <code class=\"language-plaintext highlighter-rouge\">CineCommand<\/code> values. Each value is equivalent to a call made in the current Lua file. It tells us which interaction is to be executed along with details of the interaction if any.<\/p>\n<p>Once the Lua script call is made, it triggers a function that inserts the corresponding <code class=\"language-plaintext highlighter-rouge\">CineCommand<\/code> value into the queue. While the Cinematic System is active, at each frame, it will go through each command in the queue and process them. If a command is completed, it will discarded from queue. If not, it just moves on to the next one.<\/p>\n<p>The <code class=\"language-plaintext highlighter-rouge\">WaitUntilDone<\/code> command is implemented using this mechanism. If there are any commands before it, it fails to register as completed. Once there are no others before, it registers as complete and the System moves onto the next one if one is there.<\/p>\n<h3 id=\"window\">Window<\/h3>\n<p>The Window class draws all windows, dialogs and messages in the game. I had to extend the <code class=\"language-plaintext highlighter-rouge\">draw-manager<\/code> with functions like <code class=\"language-plaintext highlighter-rouge\">loadFont<\/code> and <code class=\"language-plaintext highlighter-rouge\">drawText<\/code>to render text on screen. Along the way, I also added getter-setter functions for the Cursor, Kerning and Leading of the font.<\/p>\n<p>Currently, this class is being used to draw Dialog messages as you can see above. If you look closely, you may see that there is a artifact problem with Dialogs which will be described in depth below.<\/p>\n<p>In the future, the Deliveries List, the Inventory and Dialog Choice boxes will be added.<\/p>\n<h3 id=\"problems\">Problems<\/h3>\n<p>Here is an account of the few problems I\u2019ve had over the past week.<\/p>\n<h3 id=\"blitting-and-clipping\">Blitting and Clipping<\/h3>\n<p>For the purpose of Blitting Pictures and Tiles, I have introduced a Global Surface. It keeps a track of the of the entire screen and calls the <code class=\"language-plaintext highlighter-rouge\">g_system-&gt;copyRectToScreen<\/code> function which keeps a track of the dirty rects and blits only them.<\/p>\n<p>At one point, the Surfaces started to throw out assertions since the Suface being blitting overstepped the bounds of the Global Surface.<\/p>\n<h3 id=\"initializing-structs\">Initializing Structs<\/h3>\n<p>I ran into a series of Read Access Violations due to reading data into initialized struct pointers. As a result, we have developed a rule to add Constructors to all structs that I define.<\/p>\n<h3 id=\"struct-arrays-instead-of-pointer-arrays\">Struct Arrays instead of Pointer Arrays<\/h3>\n<p>In the beginning, I was keeping a number of struct arrays either in the form of <code class=\"language-plaintext highlighter-rouge\">T *arr[size]<\/code>, or using <code class=\"language-plaintext highlighter-rouge\">Common::Array&lt;&gt;<\/code> with the general understanding that it would be easier to reference the structs by pointers rather the value. However, since then I have realized that they merely serve to hold data and not modify them. Moreover, there are a number of them and initializing each and every one of them was getting hectic. So, I have<\/p>\n<h3 id=\"cinematic-system-and-blocking\">Cinematic System and Blocking<\/h3>\n<p>As you can see above, the Cinematic System is getting blocked while executing the <code class=\"language-plaintext highlighter-rouge\">C_MOVEENTITY<\/code> command for Sarge in the opening cinematic. Instead of stopping when she has reached her goal, she keeps on moving forward and never stops, just blocking the Cinematic system. Not sure why this is happening yet, but it needs to be solved.<\/p>\n<h3 id=\"the-dissolving-screen-problem\">The Dissolving Screen Problem<\/h3>\n<p>In the previous update, it was mentioned that we had implmeneted a hack to get the scene drawing without calling <code class=\"language-plaintext highlighter-rouge\">startMap<\/code>. While it is still not implemented, the <code class=\"language-plaintext highlighter-rouge\">centerXY<\/code> and <code class=\"language-plaintext highlighter-rouge\">drawSky<\/code> functions are now being called directly through the main game loop for now, so the XY-cructch is no longer needed.<\/p>\n<p>However, while implementing <code class=\"language-plaintext highlighter-rouge\">drawSky<\/code>, a different problem appeared. When it was called, it would creating a strange dissolving effect on screen, wherein the pixels on the scren would drive down with the drawn stars. While bizarre at first, it was being caused because the screen was not being cleared each frame for <code class=\"language-plaintext highlighter-rouge\">drawSky<\/code>. An obvious mistake perhaps, but something that stumped me nonetheless.<\/p>\n<h3 id=\"void-pointers\">Void Pointers<\/h3>\n<p>I\u2019ve started to notice a pattern in the original HDB sources. For the purpose of moving data from files to object, they relied heavily on typecasting. They would load and store data in <code class=\"language-plaintext highlighter-rouge\">void*<\/code> pointers, which would be casted at the time of usage to a particular struct. This might not seem like a big deal at first, but two problems arise:<\/p>\n<ol>\n<li>Portablity: Due to different architectures, we cannot blindly casted void pointers and expect no problems. We have to explicity define struct types and load them through the ScummVM API.<\/li>\n<li>Void Pointers can hold anything: Since void pointers can hold references of any type, at many places they have been used to hold values whose type could only be determined at runtime. Worse were situations where functions were returning void pointers, whose type could only be determined at runtime.\n<p>Due to the static nature of C++, converting such code to explicit types required me to split such functions into multiple variants and introduce union types in their structs.<\/li>\n<\/ol>\n<h3 id=\"font-header-problem\">Font Header Problem<\/h3>\n<p>At its core, this was another type problem, except perpretrated by myself. Most of the structs in the game hold positive data, so I have developed a tendency to use unsigned types for them.<\/p>\n<p>This caused a problem here since I wasn\u2019t expecting a negative number in the <code class=\"language-plaintext highlighter-rouge\">_fontHeader<\/code> data. Moreover, I had been reading the data 16 bits at a time, whereas I should have employed 32 bits. This led to wildly inaccurate header information due to which I couldn\u2019t render the messages.<\/p>\n<h3 id=\"dialog-artifact-problems\">Dialog artifact problems<\/h3>\n<p>If you look closely at the above image of the Dialog box, you might see it has dark black artifacts near the top line. Here\u2019s how those happened.<\/p>\n<p>The Dialog works is composed of 9 smaller images: TopLeft, TopMiddle, TopRight, Left, Middle, Right, BottomLeft, BottomMiddle and BottomRight.<\/p>\n<p>Depending on the length of the message, the Middle images are repeated as set number of times. When I implemented the <code class=\"language-plaintext highlighter-rouge\">drawDialog<\/code> function, there were transparency artifacts as well. However, replacing some of the <code class=\"language-plaintext highlighter-rouge\">draw<\/code> calls with <code class=\"language-plaintext highlighter-rouge\">drawMasked<\/code> solved that.<\/p>\n<h3 id=\"objectives\">Objectives<\/h3>\n<ol>\n<li>Debug and fix the moving code for Entities so Sarge stops walking when she reaches her goal.<\/li>\n<li>Figure out the correct file for the Dialog image.<\/li>\n<li>Implement the Bots code<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>It\u2019s been a long week, and I had to implement two whole sub-systems during this time: AI and Window. Both of them are currently a work in progress, but they have produced tangible results on screen. Building out these two systems, I have faced a fair share of problems which will be discussed below. This [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-28","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/blogs.scummvm.org\/nipungarg\/wp-json\/wp\/v2\/posts\/28","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.scummvm.org\/nipungarg\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.scummvm.org\/nipungarg\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.scummvm.org\/nipungarg\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.scummvm.org\/nipungarg\/wp-json\/wp\/v2\/comments?post=28"}],"version-history":[{"count":2,"href":"https:\/\/blogs.scummvm.org\/nipungarg\/wp-json\/wp\/v2\/posts\/28\/revisions"}],"predecessor-version":[{"id":31,"href":"https:\/\/blogs.scummvm.org\/nipungarg\/wp-json\/wp\/v2\/posts\/28\/revisions\/31"}],"wp:attachment":[{"href":"https:\/\/blogs.scummvm.org\/nipungarg\/wp-json\/wp\/v2\/media?parent=28"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.scummvm.org\/nipungarg\/wp-json\/wp\/v2\/categories?post=28"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.scummvm.org\/nipungarg\/wp-json\/wp\/v2\/tags?post=28"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}