mercoledì 27 aprile 2022

FREEDOM FIGHTER SMOOTH SCROLLING (ENG)



Finally, after making you wait too long, I am about to reveal how Freedom Fighter's smooth scrolling works.

Since I have to assume that the article will be read also by people who are not familiar with the MSX system (and, in this specific case, MSX1) I'll have to mention how the video memory (VRAM) of this system is organized (at least in the Graphic2 video mode, which is the one used in Freedom Fighter).

Let's start with the nametable. The nametable is the screen area, the one where in all systems (at least the ones I know) the characters that appear on the screen are "contained". The MSX screen has a resolution of 256x192 pixels. So it is made up of 24 lines. Each of them contains 32 characters (8x8 pixels). In total we therefore have 768 characters, so the nametable is 768 bytes long.
The particularity of the MSX, compared to other computers, concerns the use of these characters. In computers like the Commodore64 we have a set of 256 characters, which can be freely positioned anywhere on the screen. In the MSX system, on the other hand, in the Graphic2 mode the screen is divided into 3 zones of 8 lines each. Each of these zones has its own set of 256 characters (32x8 = 256) so the screen can be filled with 768 unique characters (very useful for bitmap graphics screens).
This means that to have the same characters in all of the 3 areas on the screen we will have to redefine them 3 times.
Much of the VRAM memory is used to memorize the shapes of the characters and their color attributes.
Each "block" of characters occupies 256x8 = 2048 Bytes. Therefore the definitions of all three character blocks use 6144 bytes of the 16384 available in the VRAM of the MSX1. The color attribute table has exactly the same length, because for each 8-pixel line of each character 2 colors can be specified (foreground and background): since the MSX1 has only 16 colors, with a single byte we can insert both (one in the high nibble and one in the low nibble). So even the color definitions occupy 6144 Bytes. In short, 12 KB are already gone for the definitions of our characters (the MSX community identifies them as "tiles").
Fortunately, once the shapes and colors have been defined, each character will have a unique code, so by recalling character 0 (for example) it will appear on the screen complete with its colors.
So as far as the characters are concerned, they occupy (including the nametable) about 13KB. The remaining 3KB contain the definitions of the 32 hardware sprites and their respective attributes (but I won't talk about it because it's not relevant to the scrolling technique I'm about to describe).

As many of you know, the MSX1 does not have any kind of hardware scrolling aid. Therefore, everything that scrolls on the screen is the result of software techniques: from block scrolling to those that in different ways have tried to bring fluidity to the shift of the screen on machines equipped with tms9918 (in its various incarnations) and compatible (therefore not only MSX but also Colecovision, Sega SG-1000 and TI99 / 4A, to name a few).

Before describing my personal technique, let's see which are the most commonly used to simulate vertical scrolling on MSX. We obviously assume that all three blocks of 256 characters are defined in the same way, because the characters that are in the first block will cross the whole screen and will then move on to the second and third blocks ...
The first technique is the simplest one. Obviously, this is block scrolling (characters), so with an 8 pixels movement at a time. As mentioned, the MSX screen consists of 24 lines of 32 characters each:



To move the content of the entire screen downwards, you need to move all the characters from the first line to the penultimate down and then draw the first line:



To speed up this operation, it's a good practice to have a copy of the nametable in a special buffer in RAM where you can quickly perform all the operations and then copy the contents to VRAM in one go. By doing this very quickly, scrolling can even seem fluid (see, for example, Konami's Road Fighter).

The second technique, commonly used to have a sufficiently fluid vertical scrolling on MSX is the 2 pixels scrolling. In practice, we have to keep stored in VRAM the various frames that make up the movement of one character to another. In this way, at each "step" of the scrolling we replace all the characters in the game area with their next frame (4 frames are needed to perform the complete scrolling of a character). After having "replaced" the characters 4 times, you return to the starting character and at the same time scroll the whole screen by 8 pixels.
Let's see an example with the Freedom Fighter graphics.



Let us consider the two highlighted characters. By performing a vertical scrolling downwards, the character of the water must slowly replace that of the shore. So the shore character will be "pushed" down 2 pixels at a time. In turn, the character immediately below (grass) will suffer the same fate due to the "shore" character and the character of the sea will also be supplanted by another character of the sea.

But maybe it is clearer with a visual example:



As you can see, the character at the top (water) in each frame is replaced with another in which the image is shifted down by 2 pixels and its first two lines contain the same data as the two lower lines of the character that is immediately above (in this case water, again)
In the same way, the character at the bottom (shore) at each frame is replaced with its image shifted by 2 pixels downwards and the first two lines contain the data of the last two of the uppermost character.
After 4 frames the classic block scrolling is carried out, whereby the character of the bank is completely replaced by that of water and that of water (in this case) by another character of water.
Let's do some calculations: 4 frames are needed for each character that must scroll, obviously related to the other characters that can be placed on it (scrolling starts in fact between 2 characters so it must be taken into account).
For which 256/4 = 64 total characters with which to build the graphics. As long as we don't need numbers and letters ... And we usually need them! Then we remove the digits 0-9. 64-10 = 54 characters. Then we remove the letters 54-26 = 28 characters with which to build the graphic. We can arrange and keep only the characters that make up the word SCORE, for example and maybe also HI so we can also have HISCORE so 54-7 = 47 characters.
From these characters we will have to organize the "pairs" of characters to scroll between them ... it follows that the graphics cannot be very varied, but for a fluid scrolling some sacrifices can also be made.
Now imagine that you want to achieve a fluid one pixel scrolling. 8 frames for each character? Forget it, come on!

Or maybe not.

 Here's how I approached the challenge for my Freedom Fighter.

The first step was obviously to decide the pairs of characters with which I would build the map (we said that scrolling always happens between two characters, right?). Let's start by saying that I have chosen to keep all the letters of the alphabet available (in addition to numbers and punctuation). Then I selected 30 pairs of characters, obtained by mixing 14 unique characters. Few to have a sufficient result. So at a certain point of the level the tileset (MSXists use the term tile to refer to the "tiles" that make up the graphics) is changed with another of 30 pairs of characters, some of which are in common, to facilitate the transition. from one tileset to another.
These are the two tilesets (3 rows of "pairs" for each tileset):



It is no coincidence that it shows you characters in pairs. It is from these pairs that the fluid scrolling of Freedom Fighter originates. Starting from these pairs, in fact, I constantly redefine the characters in order to "simulate" a scrolling. And I do it like this. The starting tile for scrolling is, between the two, the character below (the one that will be "interpenetrated" by the character above). The work that is performed, for each shift of a pixel (and for each pair of characters) is this:



These pairs of tiles are stored in the ROM of the cartridge (but in the very first version of the scrolling routine they were stored in RAM) one after the other, first the character definitions and then the color attributes. So from each pair of tiles I "extract" (pointing to the right memory location with an offset) the 8 bytes of the character definition and write them in VRAM, in all three character blocks. Then I repeat the operation for the color attributes: I extract the corresponding 8 bytes of the 30 characters and write them in VRAM in all three blocks.




Doing a quick calculation, to move the screen by one pixel I write in VRAM 8x30x3x2 = 1440 bytes. This leads to some problems: our MSX, in fact, cannot write all that data in VRAM during a single frame. The very first version of this routine, in fact, although fluid, presented several flickers and flashes. This is because often the raster beam reaches some characters while they are redefined and thus the modification of the characters and/or colors is visible.
To overcome this drawback it was necessary to implement a double buffer: in practice it was a matter of redefining characters NOT displayed on the screen and then swapping them once the process was finished. My solution was to use characters 128-157. So the "primary" characters are 0-29 and the "secondary" ones are 128-157.
The level map is unpacked in RAM (occupying just over 9 K) before the start of the level and the characters that form it are all belonging to the range 0-29.
Each time the character redefinition process is completed, a flag is updated to let us know which characters need to be redefined and which ones to show. So if we have to show the secondary characters, each value of the portion of the map displayed on the screen is read and an "xor 128" is made for each one (but it could also have been a simple sum) to point to the corresponding secondary character, before sending it to the screen.
Once the 7 pixel scrolling has been carried out, the offset of characters and colors are reset and a scrolling of one character is performed. Also in this case, having the whole map in RAM, it is sufficient to move the offset of the area to be copied to the nametable by 32 bytes back (the map is stored as seen on the screen).



When it is necessary to change tilesets, to add variety, we simply change the initial offsets pointing to the area of the ROM where the secondary tileset is stored.
I hope that this article hasn't bored you to death, but instead that it is an incentive to create your own technique or, why not, to improve this!
Soon (01/06/2022) I will declare Freedom Fighter as freeware and publish the code on Github. Be good when you look at it, I learned how to program in assembly by creating it!

2 commenti: