Loading pictures

Yes, loads of them! Let me show you the events of the past few days in the form of a screenshot first, and then I’ll wrote about them in detail. Here you go:

The first thing you may have noticed looking the picture is that I changed back the resolution to 640×200. I decided to do so because I got the information that DOSBox only emulates the bigger screen height, and as Thomas said in a comment under my previous post, Avalanche really uses 200 pixel height, so I don’t see the point in mimicking DOSBox’s output instead of recreating the original experience. Also, if we decide that a bigger resolution would be nicer, it wouldn’t take much more than adding a few lines of code to Graph::refreshScreen().

The second one is that there are much more things in the picture. Yes, I can say that the toolbar on the bottom is almost fully done and only the clock is missing from it. (Which – I assume – will miss for a couple of days/weeks because it’s not so important regrading the actual gameplay, but tricky enough to recreate. And now I have much more urgent tasks to deal with before midterm – the characters, the dropdown menu on the top and the keyboard/mouse input -, and the days are just getting shorter and shorter.)
To be honest, after understanding how EGA graphics work and implementing the loading of the background image, the toolbar itself wasn’t such a big problem, since it uses an almost identical method to load the parts of it as pictures. I can divide the bottom of the screen to 5 bigger parts: the background of the toolbar (the big blue thing), the “Thinks:” field of it, the score display, the clock, and that little picture (in the above screenshot a brown STOP sign) at the top left of it which tells the player if Avalot is standing in one place or moving in a given direction.
I implemented these parts in the exact order as I enumerated them in my previous sentence. To do this, I had to find out (obviously, with the help of fuzzie) that these pictures’ encoding differ a bit from the background’s. They are using row-planar EGA data, instead of graphic-planar EGA data which I used in the algorithm published in my previous post. Luckily, the methods for these two styles don’t differ much, so the implementation of a function which will handle all of the pictures what are not the background was quite easy. To do so, I reworked Graph a little bit, and finally Graph::drawPicture() was born (to replace Graph::copySurface()):

void Graph::drawPicture(const byte *source, uint16 destX, uint16 destY) {
 // The height and the width are stored in 2-2 bytes. We have to add 1 to each because Pascal stores the value of them -1.
 uint16 pictureWidth = READ_LE_UINT16(source) + 1;
 uint16 pictureHeight = READ_LE_UINT16(source + 2) + 1;

 uint32 i = 4;

 Graphics::Surface picture; // We make a Surface object for the picture itself.

 picture.create(pictureWidth, pictureHeight, Graphics::PixelFormat::createFormatCLUT8());

 // Produce the picture.
 for (byte y = 0; y < pictureHeight; y++)
  for (int8 plane = 3; plane >= 0; plane--) // The planes are in the opposite way.
   for (uint16 x = 0; x < pictureWidth; x += 8) {
    byte pixel = source[i++];
    for (byte i = 0; i < 8; i++) {
     byte pixelBit = (pixel >> i) & 1;
     *(byte *)picture.getBasePtr(x + 7 - i, y) += (pixelBit << plane);
    } 
   }

 // Copy the picture to a given place on the screen.
 for (uint16 y = 0; y < picture.h; y++)
  for (uint16 x = 0; x < picture.w; x++)
   *(byte *)_surface.getBasePtr(x + destX, y + destY) = *(byte *)picture.getBasePtr(x, y);  
}

During the implementation of it, I found this little help during a simple search with Google. You can see that my code dips a lot from it: I read in the width and the height of the picture first, then create a Graphics::Surface object to store the picture in it, and then a very familiar algorithm comes with a little modification regarding the order of the planes. At last, I copy the image to a given point of the screen. So Tom Swigle, if you are reading this post somewhere, sometime: thank you, you are awesome!
After I finished with drawPicture, my only task was to replace the original PutImage() calls of the Pascal code with it, since I’ve done the loading of the pictures into byte arrays (what drawPicture gets as a parameter to work with) a few weeks earlier. And that’s all, you can see yourself the result of it in the image above.

The last thing you might have noticed in the screenshot is a little pink rectangle in the middle of the screen. Don’t worry, it’s not a glitch! It’s the very place where the hero of the game, Avalot d’ Argent himself will manifest – I hope – within a couple of days. (I just put it there to see if I get the coordinates of the character accurately.)
Maybe next time we can see him in the screen as well? 😉