{"id":23,"date":"2019-06-09T09:44:38","date_gmt":"2019-06-09T09:44:38","guid":{"rendered":"https:\/\/blogs.scummvm.org\/nipungarg\/?p=23"},"modified":"2022-05-22T09:47:19","modified_gmt":"2022-05-22T09:47:19","slug":"gsoc-update-week-2-5","status":"publish","type":"post","link":"https:\/\/blogs.scummvm.org\/nipungarg\/2019\/06\/09\/gsoc-update-week-2-5\/","title":{"rendered":"GSOC Update: Week 2.5"},"content":{"rendered":"<p>Since I won\u2019t be available during Week 3 and I have gotten somewhere over the past two days, this seems like an appropriate moment for an update.<\/p>\n<p>I dedicated the past few days with drawing the first level. Naturally, this led to the <code class=\"language-plaintext highlighter-rouge\">map-loader<\/code> class. What I didn\u2019t expect at first was that my <code class=\"language-plaintext highlighter-rouge\">draw-manager<\/code> was woefully incomplete. Hence, it took some back and forth between the two to finally get the first level going.<\/p>\n<h3 id=\"first-level\">First Level<\/h3>\n<p>The good things first, here\u2019s the partial image of the first level.<\/p>\n<p><a href=\"https:\/\/blogs.scummvm.org\/nipungarg\/wp-content\/uploads\/sites\/28\/2019\/06\/firstMapDrawn.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-25\" src=\"https:\/\/blogs.scummvm.org\/nipungarg\/wp-content\/uploads\/sites\/28\/2019\/06\/firstMapDrawn.png\" alt=\"\" width=\"802\" height=\"640\" srcset=\"https:\/\/blogs.scummvm.org\/nipungarg\/wp-content\/uploads\/sites\/28\/2019\/06\/firstMapDrawn.png 802w, https:\/\/blogs.scummvm.org\/nipungarg\/wp-content\/uploads\/sites\/28\/2019\/06\/firstMapDrawn-300x239.png 300w, https:\/\/blogs.scummvm.org\/nipungarg\/wp-content\/uploads\/sites\/28\/2019\/06\/firstMapDrawn-768x613.png 768w\" sizes=\"auto, (max-width: 802px) 100vw, 802px\" \/><\/a><\/p>\n<p>It looks blocky and incomplete since more than half of the drawing functionalities aren\u2019t finished yet. In fact, it\u2019s only drawing a portion of foreground tiles at this moment. At this point, I can easily blit Tiles and Pictures to the screen but haven\u2019t got started with Masked Blitting, and Alpha-blended Blitting.<\/p>\n<h3 id=\"how-i-got-here\">How I Got Here<\/h3>\n<p>To put it simply, HDB draws in a number of different layers, ranging from 2 to 4 depending on the level. Each level consists of a Background and a Foreground. Certain levels have an additional layer below the Background, known as the Sky Layer. The Sky tiles are clubbed together with the Background tiles in memory but are drawn separately. Moreover, in certain places, the foreground tiles have gratings placed over them, so those have to be separately rendered as Masked Tiles.<\/p>\n<p>When the <code class=\"language-plaintext highlighter-rouge\">draw-manager<\/code> is initiated, it creates a reference table for all the tiles in the game. Note, no MSM files or tile data is loaded at this point. Alongside the <code class=\"language-plaintext highlighter-rouge\">init<\/code> function, <code class=\"language-plaintext highlighter-rouge\">draw-manager<\/code> provides a set of helper functions for drawing tiles, skies, stars, etc.<\/p>\n<p>Broadly speaking, the <code class=\"language-plaintext highlighter-rouge\">map-loader<\/code> utilizes three different functions to draw the map: <code class=\"language-plaintext highlighter-rouge\">loadTiles<\/code>, <code class=\"language-plaintext highlighter-rouge\">load<\/code>, and <code class=\"language-plaintext highlighter-rouge\">draw<\/code>.<\/p>\n<ol>\n<li><code class=\"language-plaintext highlighter-rouge\">load<\/code>: It takes the MSM file wrapped in a SeekableReadStream as input, and loads the different portions of the file into the <code class=\"language-plaintext highlighter-rouge\">Map<\/code> member variables. It also calls <code class=\"language-plaintext highlighter-rouge\">loadTiles<\/code>.<\/li>\n<li><code class=\"language-plaintext highlighter-rouge\">loadTiles<\/code>: For all the tiles present in the current map, its load their tile data memory, and updates the reference table created in <code class=\"language-plaintext highlighter-rouge\">draw-manager<\/code>. It also tells us which Sky tile, if any.<\/li>\n<li><code class=\"language-plaintext highlighter-rouge\">draw<\/code>: It iterates over all the loaded tiles, and draws all the background tiles. It also marks all the foreground, and grating tiles, indicating which blitting method is to be used with them.<\/li>\n<\/ol>\n<p>The Skies, Foregrounds, and Gratings are drawn through separate draw functions, which are still stubbed out. They will be discussed in the next update.<\/p>\n<h3 id=\"the-xy-crutch\">The XY-Crutch<\/h3>\n<p>This is one of the main problems that I encountered over the past few days. It occurred because a) I didn\u2019t trace the call stack that is used to start a map completely and b) due to the structure of MSM file.<\/p>\n<p>In a nutshell, in each level, the hero has a starting position. The <code class=\"language-plaintext highlighter-rouge\">Map::draw<\/code> function works on the assumption that the map has been centered to the hero\u2019s starting position. The code that fetches the foreground indices does so relative to the position that the map has been centered on, referred to as <code class=\"language-plaintext highlighter-rouge\">_mapX<\/code> and <code class=\"language-plaintext highlighter-rouge\">_mapY<\/code>. If I had fully traced the <code class=\"language-plaintext highlighter-rouge\">Game::StartMap<\/code> function in the original, I would have figured this out sooner. Hence, simply calling the <code class=\"language-plaintext highlighter-rouge\">draw<\/code> function from the main file fed garbage values to the foreground indices, and I kept getting an out-of-bounds error from them.<\/p>\n<p>While tracing the entire <code class=\"language-plaintext highlighter-rouge\">Game::StartMap<\/code> function would have been a good idea, we ended up reading the MSM file in a hex editor. At the foreground offset(0x343C), we found a series of FF values which continued as we reached 0x3A2C. From there on, a clear pattern emerged that you can see below.<\/p>\n<p><a href=\"https:\/\/blogs.scummvm.org\/nipungarg\/wp-content\/uploads\/sites\/28\/2019\/06\/map00MSM.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-26\" src=\"https:\/\/blogs.scummvm.org\/nipungarg\/wp-content\/uploads\/sites\/28\/2019\/06\/map00MSM.png\" alt=\"\" width=\"708\" height=\"579\" srcset=\"https:\/\/blogs.scummvm.org\/nipungarg\/wp-content\/uploads\/sites\/28\/2019\/06\/map00MSM.png 708w, https:\/\/blogs.scummvm.org\/nipungarg\/wp-content\/uploads\/sites\/28\/2019\/06\/map00MSM-300x245.png 300w\" sizes=\"auto, (max-width: 708px) 100vw, 708px\" \/><\/a>So right now, what we have done is set <code class=\"language-plaintext highlighter-rouge\">_mapX<\/code> and <code class=\"language-plaintext highlighter-rouge\">_mapY<\/code> to predefined values in accordance with the above pattern. This has been of some use, and now we can draw the partial map that you saw above. However, even this does not allow all the foreground tiles to be drawn. My next order of business would be to properly implement the <code class=\"language-plaintext highlighter-rouge\">Game::StartMap<\/code> to the extent that I can right now so <code class=\"language-plaintext highlighter-rouge\">_mapX<\/code> and <code class=\"language-plaintext highlighter-rouge\">_mapY<\/code> don\u2019t have to depend on predefined values.<\/p>\n<h3 id=\"avoidable-problems-and-missing-files\">Avoidable Problems and Missing Files<\/h3>\n<p>There was another stupid bug that I should\u2019ve caught earlier. Since I managed to spend more than an hour debugging this, I think it deserves a mention. If anything, it demonstrates how easy it is for a game-breaking bug to slip in if you\u2019re not careful.<\/p>\n<p>The <code class=\"language-plaintext highlighter-rouge\">draw-manager<\/code> has a set of three Sky tiles that are always loaded into memory whenever the <code class=\"language-plaintext highlighter-rouge\">draw-manager<\/code> is initiated, regardless of the <code class=\"language-plaintext highlighter-rouge\">map-loader<\/code>. Once I started debugging the <code class=\"language-plaintext highlighter-rouge\">Map::draw<\/code> function, it became apparent to me that these tiles were not getting loaded.<\/p>\n<p>Since I had been dealing with missing for a while now, I decided to check that over. Thankfully, the files were present in the archive. However, it seemed that the <code class=\"language-plaintext highlighter-rouge\">draw-manager<\/code> refused to acknowledge that they were present. From there, I thought that the tile reference table might be messing up the Sky tiles. I went through the <code class=\"language-plaintext highlighter-rouge\">init<\/code> function, checking and rechecking the tile reference table code. Along the way, I improved the code with more standard methods but it still gave the same error.<\/p>\n<p>At this point, I was fairly certain that the Sky tiles existed, and the reference table was aware of them. Then, the logical conclusion becomes that the Sky tile was messing up the indices somehow. The Sky tile code is distributed throughout three functions: <code class=\"language-plaintext highlighter-rouge\">drawSky<\/code>, <code class=\"language-plaintext highlighter-rouge\">isSky<\/code>, <code class=\"language-plaintext highlighter-rouge\">setSky<\/code>. They interact with each other, and that made it slightly hard to think of them intuitively. I soon learnt that the wrong Sky index was being passed into the function calls, and at the root of it was <code class=\"language-plaintext highlighter-rouge\">isSky<\/code>. Simply speaking, <code class=\"language-plaintext highlighter-rouge\">isSky<\/code> checks if a tile is a Sky tile and returns its skyIndex. Since there only 7 Sky tiles, they are indexed in a Sky tile array, indexed from 0 to 6. This array maps the skyIndex to the corresponding index of the tile reference table.<\/p>\n<p>My mistake was that I had set <code class=\"language-plaintext highlighter-rouge\">isSky<\/code> to return <code class=\"language-plaintext highlighter-rouge\">index + 1<\/code>, where <code class=\"language-plaintext highlighter-rouge\">index<\/code> is the tile index of the input tile. So instead of returning an index for the Sky tile array, it was returning an index for the tile reference table \u2014 and a completely wrong index at that! Changing <code class=\"language-plaintext highlighter-rouge\">index + 1<\/code> to <code class=\"language-plaintext highlighter-rouge\">i + 1<\/code> solved the problem.<\/p>\n<p>Another issue: I\u2019m still getting used to <code class=\"language-plaintext highlighter-rouge\">git<\/code> in a project of this size. One thing that happened this week: I added a few lines that I thought were perfectly correct, and I pushed them to my remote. As one might expect, the changes broke the project to the point it stopped compiling. After I had corrected the problems, sev has given me a simple workflow to standardize commits:<\/p>\n<pre class=\"highlight\"><code>Compile -&gt; Diff -&gt; Commit<\/code><\/pre>\n<p>A similar thing happened during the debug process. I had to rebase a few commits sev had pushed. There were a few merge conflicts, and I accidentally overwrote the changes that I had rebased for. In a hurry to correct the changes, I reset my local branch by three commits. Thankfully, I had merely added a few declarations and small initializations at that point which was easy to replicate.<\/p>\n<p>Apart from my own foolishness, I found that certain files were missing from the MPC demo. According to the original source code, it should have been packaged with both the demo and the full version. In the beginning, I had started building the HDB engine based on the demo files. After this, I had to switch files and now I\u2019m basing it on the full game.<\/p>\n<h3 id=\"objectives\">Objectives<\/h3>\n<ol>\n<li>Trace and implement the StartMap function.<\/li>\n<li>Add the Masked Blitting and Alpha Blitting functions to DrawMan.<\/li>\n<li>Complete the stubbed-out drawSky functions.<\/li>\n<li>Add code to draw Foregrounds and Gratings.<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>Since I won\u2019t be available during Week 3 and I have gotten somewhere over the past two days, this seems like an appropriate moment for an update. I dedicated the past few days with drawing the first level. Naturally, this led to the map-loader class. What I didn\u2019t expect at first was that my draw-manager [&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-23","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/blogs.scummvm.org\/nipungarg\/wp-json\/wp\/v2\/posts\/23","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=23"}],"version-history":[{"count":2,"href":"https:\/\/blogs.scummvm.org\/nipungarg\/wp-json\/wp\/v2\/posts\/23\/revisions"}],"predecessor-version":[{"id":27,"href":"https:\/\/blogs.scummvm.org\/nipungarg\/wp-json\/wp\/v2\/posts\/23\/revisions\/27"}],"wp:attachment":[{"href":"https:\/\/blogs.scummvm.org\/nipungarg\/wp-json\/wp\/v2\/media?parent=23"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.scummvm.org\/nipungarg\/wp-json\/wp\/v2\/categories?post=23"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.scummvm.org\/nipungarg\/wp-json\/wp\/v2\/tags?post=23"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}