Afficher une image en assembleur sur Atari ST

Vretrocomputing Display a picture in assembly language on Atari ST Hi, all! Today, I’m going to show you how to display a picture in assembly language on Atari ST. Last time, I showed you how to display text. Well, to display an image, it’s almost as simple. As an example, I will use Lenna’s famous photo. This is undoubtedly the most used photo for image processing tests since 1973. To be able to display it in low resolution, I converted it to 320×200, 16 colors. And I saved it in uncompressed Degas format with extension .PI1 Like last time, I prepare a floppy disk to work with Devpac. It contains the following files: GENST2.PRG: it’s the editor and the assembler. His companion MONST2.PRG, the debugger. And finally, the image we want to display: LENNA.PI1 If I look at the properties of this PI1 file, I see that it is exactly 32034 bytes. And it’s the same for all the PI1 files saved by Degas. Here is the explanation. In a previous video, I told you about the 3 video modes of the Atari ST: low resolution, medium resolution, and high resolution. Well, know that in each of these 3 modes, the image occupies exactly 32000 bytes. That’s why the PI1 files are about 32 KB. More precisely, here is what PI1 files contain. By the way, I remind that the word “offset” means:
distance in bytes from the beginning of the file. First, there are 2 bytes indicating the resolution. Then 32 bytes for the color table, also called “palette”. And finally, the 32000 bytes of the image itself. This sums up to 32034 bytes. It’s what we expected! And for precision, I add that PI1 files saved by Degas Elite are 32066 bytes. This is because they include 32 extra bytes to define color animations. But as this information is stored after the image data, it is not a problem. After the theory, let’s practice. I switch to medium resolution, I run GENST2.PRG, and I don’t forget to save regularly. I start by putting a comment at the beginning of the file to indicate what the program will do. The first question to ask is:
How will the program access the image? The simplest way is to include the PI1 file directly in the program with the INCBIN directive. It means: Include Binary. I start by defining a label which will allow to reference the data. I name it pi1, for example. And I type: INCBIN lenna.pi1 The INCBIN directive is very convenient: It’s exactly as if I used DC.B to define 32034 bytes of data. Now, how are we going to display this image? On Atari ST, the image is produced from a framebuffer, also called “video memory”. This is a memory area that contains the entire displayed image. And it’s the same on most modern machines. On Atari ST, the framebuffer resides in the main RAM. It can therefore be accessed very easily, like any other memory area. To manipulate the framebuffer, we will use the XBIOS. As I explained in the magazine Programmez! #°229, XBIOS is the lowest layer of TOS. Specifically, we will use the XBIOS function number 3 called Logbase(). It simply returns a pointer to the framebuffer. As usual, I push the number of the function to the stack: 3 Then I call the XBIOS layer with the instruction “trap #14”. And I fix the stack. The Logbase() function returns the framebuffer address in the d0 register. I put it safe in the register a3. Now I have to copy the image to the framebuffer. We have just seen that, in a PI1 file, the image data is at offset 34. So I use the expression “move.l #pi1+34,a0” to point a0 to the image. This will be our source pointer. I then take the address of the framebuffer I kept in a3, and I put it into a1. This will be our destination pointer. Then we have to copy the data from a0 to a1. For that, I’m going to use a simple loop over the MOVE.L instruction. This is not the fastest method, but it is the simplest. I told you that the size of the framebuffer was always 32000 bytes. For its part, the instruction “move.l” deals with a long word at a time. That is to say, 4 bytes. So to know how many times I have to call the “move.l” instruction, I have to divide 32000 by 4. Result is: 8000. To loop 8000 times, I have to use the “dbf” instruction, also called “dbra”. It needs to be initialized with the number of iterations minus 1. In our case, 8000 – 1=7999. So I put this value into a register, for example d0. I could specify this number directly. But if I reread this program in a few days, I may have forgotten how I found this value. So for ease of understanding, I put the formula in the source: 32000/4-1. The actual value will be calculated by Devpac at assembly time. So don’t worry, this doesn’t cause any performance issue. I can finally write the body of the loop. I start by placing a label, which I name “copie”, for example. Then I copy a long word from a0 to a1, with postincrementation. It means that after the instruction, these two registers will point to the next long words. And I use the “dbf” instruction to loop. The first parameter is the register used for the counter, and the second parameter is the label at the start of the loop. That’s it! These few instructions are enough to copy the image to the screen. To admire the result, you know what’s left to do: Wait for a key press with Cnecin(), and terminate the program with Pterm0(). Now, I can assemble. As usual, I check Memory. But as our program will be more than 32 KB, I need to increase the maximum size of the memory buffer. For example: 100 KB I click on Assemble. OK, no error. And I run. Um. This is not really what we expected. We can vaguely distinguish the facial features of the young lady, but there are vertical bands with alternating colors. Look closely at this picture, because it is a typical result. This happens when we try to display a low resolution image while being in medium resolution. And that’s precisely our case. What can we do ? A solution would be to run Devpac from low resolution. But this is not convenient because in low resolution, there is not enough width to display our entire program. Instead, we will use another solution: We will switch to low resolution at the beginning of our program. For that, we will use the XBIOS function number 5 called Setscreen(). It allows to change several display settings, including: the resolution. And this is, by the way, the first parameter to push. To switch to low resolution, we need to pass the value 0. Thus I can use the instruction “clr.w”. Then there are 2 other parameters. Since we do not want to modify them, we simply pass the value -1. Then there is the function number, in this case: 5 We call the XBIOS with “trap #14”, and we fix the stack. To assemble again, without going through the dialog box, I recommend the keyboard shortcut Shift+Alt+A. It’s very fast. And we run with Alt+X. Ah! This time, we can recognize the young woman. But the colors are wrong. This is because, for the moment, we have only cared about the image data, that is to say: pixels. We must now take care of the color palette. For that, we will use the XBIOS function number 6 called Setpalette(). It is very easy to use. First, we need to push the address of the new palette. We saw earlier that the palette of the image is stored in the PI1 file at offset 2. So I just need to push the expression “#pi1+2” on the stack. I push the function number: 6 Then I call the XBIOS, and I fix the stack. I assemble. I run. Great! It works. We can now contemplate Lenna with her true colors. There is still a small detail to fix. If I move the mouse, an ugly rectangle appears, as well as the bee-shaped cursor. To avoid that, we have to hide the mouse before displaying the picture. The mouse display is managed by another layer of TOS called “Line-A”. Most TOS layers can be called with the “trap” instruction. But the Line-A is an exception to the rule: To call it, we have to use special opcodes that start with A and end with the function number in hexadecimal. For now, just remember this: To hide the mouse, use Line-A function number 10. It can be called with the directive “DC.W $a00a”. And that’s enough. Now, when I move the mouse, nothing happens. Our problem has disappeared. So our program is finished. That’s all. I showed you how to display an image on Atari ST using XBIOS. We have to remember that the XBIOS gives direct access to the framebuffer and to the palette. So we can display everything we want on the screen, make animations … But that will be for another time. So for now, I just say: See you soon, for new tutorials! And don’t forget to subscribe 😉

Tags: , , , , , , , , , , , , , , , ,


  • Jean Monos says:

    intéressant merci M.

  • LeGlod says:

    Je sais plus mais je crois que certaines version de Neochrome Master ou peut etre une autre soft oubllie 2 octets à l'image PI1 32032 et du coup cela faisait planter d'autres soft ou certaines routine. Ou une histoire comme ça, je me rappel plus.

Leave a Reply

Your email address will not be published. Required fields are marked *