{"id":26,"date":"2013-07-14T16:56:28","date_gmt":"2013-07-14T16:56:28","guid":{"rendered":"https:\/\/blogs.scummvm.org\/uruk\/?p=26"},"modified":"2022-05-22T13:50:51","modified_gmt":"2022-05-22T13:50:51","slug":"first-screenshot","status":"publish","type":"post","link":"https:\/\/blogs.scummvm.org\/uruk\/2013\/07\/14\/first-screenshot\/","title":{"rendered":"First screenshot"},"content":{"rendered":"<p>Yes, you are not dreaming! It&#8217;s true, it&#8217;s fresh, it&#8217;s happening\u00a0<u><b>RIGHT NOW<\/b><\/u>! Ladies and gentlemen, I proudly present you the very first screenshot of Avalot d&#8217; Argent in the holy embrace of SvummVM!<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blogs.scummvm.org\/uruk\/wp-content\/uploads\/sites\/48\/2022\/05\/comparison.png\" \/><\/p>\n<div class=\"separator\"><\/div>\n<p>Okay, the colors really need some adjustments, but apart from that you can see that the background image is successfully loaded and shown accurately. (Of course here will come the GUI in the top and the bottom, but that&#8217;s not my first priority at the moment.)<\/p>\n<figure style=\"width: 400px\" class=\"wp-caption alignright\"><a href=\"https:\/\/blogs.scummvm.org\/uruk\/wp-content\/uploads\/sites\/48\/2022\/05\/alfalfa-herbal-remedies-1.jpeg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.scummvm.org\/uruk\/wp-content\/uploads\/sites\/48\/2022\/05\/alfalfa-herbal-remedies-1.jpeg\" alt=\"\" width=\"400\" height=\"300\" \/><\/a><figcaption class=\"wp-caption-text\">Lucerna<\/figcaption><\/figure>\n<p>Let me tell you a little story about my fight with the bits! Everything started after my latest post: I began to mess around with graphics, and I had some mailing with dreammaster, who helped me a lot and gave me an awesome &#8220;Graphics in ScummVM for dummies&#8221; guide. By following that, I successfully set up the basics of the screen handling in my engine, what you can find\u00a0<a href=\"https:\/\/github.com\/urukgit\/scummvm\/blob\/avalanche\/engines\/avalanche\/graph.h\" target=\"_blank\" rel=\"noopener\">here<\/a>\u00a0and\u00a0<a href=\"https:\/\/github.com\/urukgit\/scummvm\/blob\/avalanche\/engines\/avalanche\/graph.cpp\" target=\"_blank\" rel=\"noopener\">here<\/a>. Graph&#8217;s initial purpose was to replace the Graph unit from Pascal with a C++ class, so it can work in synergy with\u00a0<a href=\"https:\/\/github.com\/urukgit\/scummvm\/blob\/avalanche\/engines\/avalanche\/original\/lucerna.pas\" target=\"_blank\" rel=\"noopener\">Lucerna<\/a>\u00a0(the class\/unit which is responsible for the screen, keyboard and mouse handling) but as time passes I am slowly getting convinced that it will eventually become a replacement for Lucerna. I don&#8217;t see it clear yet, time will tell&#8230;<\/p>\n<div class=\"separator\">At the moment Graph is not much more than a wrapper around a Graphics::Surface object.<\/div>\n<div class=\"separator\">I got the resolution of the game (what you can find in the header file of Graph) from this function call in the original code:<\/div>\n<div class=\"separator\">\u00a0gd:=3; gm:=0; initgraph(gd,gm,&#8221;);<\/div>\n<div class=\"separator\">Where 3 stands for EGA graphic driver and 0 means EGALo mode, which is equal to 640&#215;200 screen resolution, 16 colors and 4 screen pages. (I&#8217;ll bother with these &#8220;pages&#8221; later.)<\/div>\n<div class=\"separator\">I also had some difficulties setting up the color palette to mimic the EGA display, but dreammaster told me a lot about it, and by &#8220;borrowing&#8221; a\u00a0<a href=\"https:\/\/github.com\/urukgit\/scummvm\/blob\/d11856078597250361328b0cc7935a1413ce2b60\/engines\/avalanche\/graph.cpp#L53\" target=\"_blank\" rel=\"noopener\">little bit of code<\/a>\u00a0from\u00a0<a href=\"https:\/\/github.com\/Strangerke\/scummvm\/blob\/mortevielle\/engines\/mortevielle\/graphics.cpp#L51\" target=\"_blank\" rel=\"noopener\">Strangerke&#8217;s Mortvielle engine<\/a>, I get over with it quite fast too. As you may see it in the screenshot at the beginning of the post, there is still a couple of things to do with it, since the colors in the original game are much more livid, but I&#8217;ll leave it&#8217;s fix for later.<\/div>\n<div class=\"separator\"><\/div>\n<div class=\"separator\">The next big deal came right after that. I had a long conversation with fuzzie (who is &#8220;substituting&#8221; Strangerke, my mentor, while he is on holiday) about the topic and she told me a great deal about EGA displays and\u00a0<a href=\"http:\/\/www.shikadi.net\/moddingwiki\/Raw_EGA_data\" target=\"_blank\" rel=\"noopener\">how did they handle data<\/a>.<\/div>\n<div class=\"separator\">The function which is responsible for loading the data of each screen is\u00a0<a href=\"https:\/\/github.com\/urukgit\/scummvm\/blob\/avalanche\/engines\/avalanche\/lucerna2.cpp#L201\" target=\"_blank\" rel=\"noopener\">Lucerna::load()<\/a>. The tricky part was here to notice the loop in the\u00a0<a href=\"https:\/\/github.com\/urukgit\/scummvm\/blob\/avalanche\/engines\/avalanche\/original\/lucerna.pas#L215\" target=\"_blank\" rel=\"noopener\">original code<\/a>\u00a0(which is fuzzie&#8217;s merit), and recognize that we have to face the &#8220;four plane style&#8221;. After that, recreating it in C++ was quite easy, and fuzzie helped me a lot with that as well.<\/div>\n<div class=\"separator\">Here&#8217;s the result of it:<\/div>\n<p>&nbsp;<\/p>\n<pre class=\"brush:cpp;\">f.seek(177);\r\n\r\n\/*for (bit = 0; bit &lt;= 3; bit++) {\r\n port[0x3c4] = 2;\r\n port[0x3ce] = 4;\r\n port[0x3c5] = 1 &lt;&lt; bit;\r\n port[0x3cf] = bit;\r\n blockread(f, a0, 12080);\r\n move(a0, a1, 12080);\r\n}*\/\r\n\r\nGraphics::Surface background;\r\nbackground.create(_vm-&gt;_graph._screenWidth, _vm-&gt;_graph._screenHeight, Graphics::PixelFormat::createFormatCLUT8());\r\n\r\nbyte backgroundHeight = 8 * 12080 \/ _vm-&gt;_graph._screenWidth; \/\/ With 640 width it's 151\r\n\/\/ The 8 = number of bits in a byte, and 12080 comes from the original code (see above)\r\n\r\nfor (byte plane = 0; plane &lt; 4; plane++)\r\n for (uint16 y = 0; y &lt; backgroundHeight; y++)\r\n  for (uint16 x = 0; x &lt; _vm-&gt;_graph._screenWidth; x += 8) {\r\n   byte pixel = f.readByte();\r\n   for (byte i = 0; i &lt; 8; i++) {\r\n    byte pixelBit = (pixel &gt;&gt; i) &amp; 1;\r\n    *(byte *)background.getBasePtr(x + 7 - i, y) += (pixelBit &lt;&lt; plane);\r\n   } \r\n  }\r\n\r\n_vm-&gt;_graph.copySurface(background);\r\n\r\nbackground.free();<\/pre>\n<div class=\"separator\"><\/div>\n<div class=\"separator\">As you can see I left the automatically converted loop in a comment. Under that, there&#8217;s my C++ interpretation of it. You can find the idea behind that loop&#8217;s core on\u00a0<a href=\"http:\/\/www.shikadi.net\/moddingwiki\/Raw_EGA_data\" target=\"_blank\" rel=\"noopener\">this page<\/a>. We guessed it&#8217;s using four planes because the original loop goes from 0 to 3. So my code does the very same. It first reads the blue component of every pixel: since every bit represent a pixel, we jump in the x loop 8 times every time, and read a byte only after every 8th processed pixel. After that, we loop through the given byte, get the blue component of every pixel, and put them in their place. We do that four times, so every plane (blue, green, red, intensity) is read by the end of the big, plane loop, and finally we got the background image!<\/div>\n<div class=\"separator\">The interesting part with this is the following: we read an image with the size of 640&#215;151. That&#8217;s ok, but after playing the game a couple of times using DOSBox, I clearly saw that it shows the background image (and obviously the whole game too) in a much bigger resolution. I found that the window&#8217;s size the emulator uses is 640&#215;400. It&#8217;s very strange since the original Pascal code (as I mentioned above) uses half of that height. To mimic DOSBox&#8217;s output, I put a little supplement into\u00a0<a href=\"https:\/\/github.com\/urukgit\/scummvm\/blob\/avalanche\/engines\/avalanche\/graph.cpp#L81\" target=\"_blank\" rel=\"noopener\">Graph::copySurface()<\/a>\u00a0which copies every line of the background 2 times. After that, my graphical output became almost the same with the one DOSBox produced, but I am still not sure if it&#8217;s the right way of operation and I am still searching for traces of this &#8220;stretching&#8221; in the original code.<\/div>\n<div class=\"separator\"><\/div>\n<div class=\"separator\">(P.s.: Thomas: if you read this post and have any clue or suggestion about this resolution-problem, I&#8217;d be very glad if you could share it with me in a comment or by mail! \ud83d\ude42 Is the original output of the game really in 640&#215;400, and if it is, where the &#8220;trick&#8221; is located in the original code which makes it possible?)<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Yes, you are not dreaming! It&#8217;s true, it&#8217;s fresh, it&#8217;s happening\u00a0RIGHT NOW! Ladies and gentlemen, I proudly present you the very first screenshot of Avalot d&#8217; Argent in the holy embrace of SvummVM! Okay, the colors really need some adjustments, but apart from that you can see that the background image is successfully loaded and [&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-26","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/blogs.scummvm.org\/uruk\/wp-json\/wp\/v2\/posts\/26","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.scummvm.org\/uruk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.scummvm.org\/uruk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.scummvm.org\/uruk\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.scummvm.org\/uruk\/wp-json\/wp\/v2\/comments?post=26"}],"version-history":[{"count":1,"href":"https:\/\/blogs.scummvm.org\/uruk\/wp-json\/wp\/v2\/posts\/26\/revisions"}],"predecessor-version":[{"id":29,"href":"https:\/\/blogs.scummvm.org\/uruk\/wp-json\/wp\/v2\/posts\/26\/revisions\/29"}],"wp:attachment":[{"href":"https:\/\/blogs.scummvm.org\/uruk\/wp-json\/wp\/v2\/media?parent=26"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.scummvm.org\/uruk\/wp-json\/wp\/v2\/categories?post=26"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.scummvm.org\/uruk\/wp-json\/wp\/v2\/tags?post=26"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}