FASE Forum messages

The whole blog should have started with this, but better late than never.

These quotes are ripped from the Mojon Twin Forum where FASE was first announced. The authors of these messages are credited.

Antonio Villena

I’m bad at putting names, I know, but until I find nothing better this will be the tentative name. The reason is because it will be an engine inspired by the Churrera. Since it’s still very green, I can not say if it’s just about inspiration or it’s plagiarism like a train, so I want to make things clear from the beginning. At the moment there is nothing written in C, D_Skywalk is going to be ordered from that, for which I am going to give you a few indications in this thread about how the assembler part works.

Since there is a lot of code, let’s start with simple things. The compilation is done with makeBu.bat when executing it, the game.tap file is generated. So far so good. The assembly part is divided into two: on the one hand is the engine itself (engine.asm) and on the other the charger c / m (loader.asm). The part in C is not made (for now there is a simple main.asm in assembler), but it would be to generate a main.bin from a main.c starting from the $ 8000 address and as a length stop or stack pointer initial $ fe50-stasp (which is a constant generated in defload.asm).

The communication of part C (which generates main.bin) with the engine is not through calls to subroutines, but through structures in memory. For example, there is a structure between $ FE00 and $ FE40 that manages the sprites, indicating their position X, Y, if it is activated or not and the sprite number to be painted. The tiles are handled with the positions $ 5b00, $ 5b01 .. $ 5b96 and $ 5bfe .. $ 5bff. In the first position, we tell the engine that we want to position ourselves on the X screen, a script in said byte causes the entire screen to be painted and the indexes of the tiles loaded into the array $ 5b01 .. $ 5b96. Now, if you want to modify the tiles of the current screen, either to animate them or to open a bolt, this is done by typing directly in $ 5b01 .. $ 5b96 and specifying the tile rectangle to be updated in $ 5bfe .. $ 5bff

Finally, say that there are certain interesting directives in engine.asm that allow us to shorten the size of it and therefore have more space for the game. The first one is smooth, if it is set to 0 half of the rotations of the sprites are stored (4 per sprite instead of 8 per sprite), which drastically reduces the size of the sprites (more or less 10K to 5K). If you change the smooth directive also removes the word dummy from the call to GfxBu (fifth line of makeBu.bat), this fudge will be removed later. Then we have the clipup and clipdn directives that if activated allow us to cut the sprites on the top and bottom of the screen, and if they are disabled we save a lot of code. Finally, we have safeco,

Do not be scared, D_Skywalk, as complicated as it seems. First, check that you can generate the functional game.tap, then you would have to pass the main.asm to main.c with the compiler you want and finally you could start writing the part of the engine in C.

Antonio Villena
5b00 number of screen to paint
5b01-5b96 tiles codes of actual screen
5bfe-5bff set to repaint a rectangular area of tiles
5c00-5c3f sprite info, where
5c00-5c02 first sprite
5c00 sprite number, set high bit to disable
5c01 X coord
5c02 Y coord
5c04-5c06 second sprite

Antonio Villena
That’s it, I’ve finished the demo as it was, including the character’s handling on the screen with the OPQA keys. The changed files are main.c, bunuelera.hy and loader.asm.

I do not have much idea in the handling of this compiler, and I do not know how to tell you the records that will crush the FRAME routine, that’s why I was failing. At the moment I have solved saving IX and BC, but it is not a definitive solution.

For the curious that do not want to get into the repository, this is the main.c:

#include  "bunuelera.h"

const unsigned char data[32]= {
  0x00, 0x42, 0x11, 0,
  0x08, 0x60, 0x60, 2,
  0x09, 0xa8, 0x48, 3,
  0x0a, 0x22, 0x02, 1,
  0x0b, 0xd0, 0x6e, 2,
  0x0c, 0xb6, 0x34, 3,
  0x0d, 0x32, 0x32, 1,
  0x04, 0x52, 0x5e, 0};

int main(){

  // variables
  int i, x= 0, y= 0;

  // pass characters to sprites
  for ( i = 0; i >2][i&3]= data[i];

  // initilize engine

  // show the first screen at the beginning
  screen= 0;


    //this causes the engine to process a frame generating the scenario

    // movement of the enemies
    for ( i = 1; i < 8; i++ ){
      if( sprites[i][3]&1 )
        if( sprites[i][2] )
          sprites[i][3]^= 1;
        if( sprites[i][2]0x08 )
          sprites[i][3]^= 2;
        if( sprites[i][1]<0xe8 )
          sprites[i][3]^= 2;

    // movement of the protagonist
    if( ~KeybYUIOP & 0x01 ){ // P
      if( sprites[0][1]<0xee )
      else if( x 0x02 )
      else if( x )
        sprites[0][1]= 0xee,
        screen= y*12 + --x;
    if( ~KeybGFDSA & 0x01 ){ // A
      if( sprites[0][2]<0xa0 )
      else if( y 0x01 )
      else if( y )
        sprites[0][2]= 0xa0,
        screen= --y*12 + x;

Antonio Villena
Since I’m going I’m going to explain how tiles work. GfxBu is responsible for processing them, we indicate in a parameter (the fourth) which mode to use. Regardless of the mode we have chosen, GfxBu will show us how much the tiles occupy in the 4 available modes: no index, index bitmap, index attr and full index with codes 0, 1, 2 and 3 respectively. The more indexed the mode, the longer the painting routine will take, although there is not much speed difference, so it is preferable to choose the mode that occupies less bytes, thus we will leave more free memory for our game.

Indexed tiles produce more redundant maps graphically, but they occupy much less. This means that with equal size, indexed tiles allow maps with a greater number of different tiles, therefore more varied than if non-indexed tiles were used, that is why it is a feature that should be exploited.

Antonio Villena
The variable screen is mapped to the address $ 5b00, this byte what it does is load the full screen with the screen number that we write on it. In the demo I keep the account of the screen number with the variables x and y. In total the demo has 12×2 screens, so “y” varies between 0 and 1 and “x” between 0 and 11. In this case, it also increases the variable “x”, indicating that we want to move to the screen on the right.

Antonio Villena
When compiling a lot of temporary files are generated, which also can not be deleted because I want to save time compiling. To see the phase .bat generates the .tap in 3 stages:
Compilation of graphics
Assembly of the engine in ASM
Compiled from the engine in C and generation of TAP

If I type ” phase gfx” the 3 stages are executed, if I type ” phase config” the last 2 are executed and if I write ” phase ” to dry only the last stage is executed. But of course this requires that the intermediate files are not deleted. Putting the intermediate files in another directory would involve using relative paths in the sources, some of them with .. \

I can separate things a bit: put the main.c and the main.bas in a separate directory, or put the graphics and the map in another directory, but as it is it is impossible to have a phase .bat (or phase .sh) simple and at the same time the root cleared of files.

Antonio Villena
I’m already finalizing the engine. As in the end it has a lot of configurable things I have no choice but to do a mini-guide (in English) to explain what the parameters affect (above all of config.def).

Here I leave an explanatory image that I just created with the gimp, I hope it is understood.

Antonio Villena
Well, basically, it’s about compiling a binary that starts at the address $ 8000 (32768) and communicates with the engine writing in the area $ 5b00- $ 5c08. There are pre-generated constants in define.h that can be very useful to you. The crux of the matter is how to map that memory area in C. With SDCC I have done it in a somewhat shabby way: the sprite number N is accessed with sprite [N] [0] for the number of sprite, sprite [N] ] [1] for the X coordinate and sprite [N] [2] for the Y coordinate. Here it would be more logical to use struct and something like sprite [N] .x.

Antonio Villena
You can also use defines:

#define SPRITE_X(n) sprite[n][1]

Antonio Villena
Another thing, in FASE I modified the converter to accept these two types of sprites:
256×32 image with 2 rows of sprites. Each sprite has a mask on its right, indicated in black with a red background. This is the format used by the Churrera.
256×16 image with 1 row of sprites. The mask is indicated in the sprite itself by transparency. It would be the new format that I have introduced following the implementation in HTML.

Antonio Villena
Leave as masked pixels that are at 1, and not only pixels that are at 0. As at the top, the mask is painted with AND (which creates a “hole” with the silhouette) and then the XOR graphic (which paints the sprite in the hole), if we put as transparent in the mask pixels that are 1 in the graph, these will be reversed if what is in the background is 1 …

The same can be done with the transparency layer. That is, you can paint pixels (in white or black) that are transparent a priority, the only thing that would not be seen. If for example we put the transparency at 50% yes we distinguish black pixels from whites where there is transparency.

The transparency in the background is as if it were another component of color more. If we take into account 2 channels (grayscale and alpha) and 2 color levels for each, the result is 2 bits per pixel image. What happens is that of these 4 values per pixel we are usually interested in three (white, black and black masked). Masked white is not used because normally the algorithm is AND / OR, although nobody prevents you from using an AND / XOR algorithm and using the fourth value to invert background colors.


Antonio, can we paint half of a sprite? Can I choose the size of the sprite to be painted?
Could you paint part of a tile?

I was thinking about doing a 16×8 sprite.
If you have to touch ASM, you do not need to, just ask to see what options we have

Antonio Villena
With sizes less than 16×16 there are no problems. The routine is adaptive, if the sprite is 8×8 it will occupy less in memory and it will take less time to paint. It is advisable that it is centered in the 16×16 box if the view is zenith, or that it is centered in the lower part if the view is lateral (so that it is levitated).

>>can I choose the size of the sprite to be painted?

No, you have to adhere to 16×16 or smaller, up to 1×1 pixel, it’s a matter of putting the indicated mask.

>>Could you paint part of a tile?

Neither. The tiles do not have a mask so they should always be 16×16. You can have the tiles you want up to 256, and although they are not compressed you can index them so that they occupy less. Indexing them is to use the same 4 attributes for several sprites, or the same bitmaps with different colors (for example a white rock and a yellow one), or combinations of both indexations.

>>I was thinking about doing a 16×8 sprite
>>If you have to touch ASM, you do not need to, just ask to see what options we have

In that case there is no problem.

Something that is strange in this engine is that you can not paint when you want. If you have to update markers you have to write the address of the function in bytes $ 5c06- $ 5c07 (variable drwout). This will be painted at the right time. Do not assume that the video memory is at $ 4000, you have to add shadow << 8 to the address before writing, since at page 128K page 7 is also used (located at $ c000- $ daff).

The use of tiles is very flexible, you can change the tiles of the current screen at your leisure with the tile array and indicate the tile rectangle to be updated with the tilepaint macro. I recommend that you read the reame.html and try to understand the demo of main.c. If you do not understand something about the demo, you know, ask.

I did not mean to paint only one area of a 16×16 sprite using a 16×8 mask, but to have sprites of 16×8 for example to have more frames for the animation, actions, etc …

The documentation I read it and then I understood it. I want to make a game for 128K so that we also have an example of how to create phases and so on, I guess it does not work for me like na_th_an does in the churrera, right?

Antonio Villena
>>I did not mean to paint only one area of a 16×16 sprite using a 16×8 mask, but to have 16×8 sprites for example to have more frames for the animation, actions, etc …

There is no easy way to put sprites of another size. But what I was saying, is so optimized that if you work a 16×8 routine, it will be as fast as using 16×16 sprites with a 16×8 mask.

>>I read the documentation and I understood the shadow. I want to make a game for 128K so that we also have an example of how to create phases and so on, I guess it does not work for me like na_th_an does in the churrera, right?

I do not know how na_th_an does it in the churrera. My idea was to evolve later PHASE so that this was transparent. In other words, you put the levels in such a way that only one level fits in 48K and all the levels together do not exceed 128K. The tool will generate a TAP that at first the machine recognizes you, and if it is 128K, it will load it all, if it is 48K, the first phase will load it (the same as many spectrum games do).

I am trying to animate the gatete and among other things it is not explained anywhere that means:
sprites []. No sprites [].
Another how to put text?

Antonio Villena
>>I am trying to animate the gatete and among other things it is not explained anywhere that means: sprites []. No sprites []

sprites []. n is to tell the engine what sprite we want to show in that entry, in readme.html comes this help:

You have 16 different sprites so you must specify what sprite you want to show. Put the high bit to 1 if you want to disable the sprite (or to hide it)

sprites []. F is the fourth byte of the input, it is useless because nothing else is used 3 bytes. But the array is aligned to 4 bytes to make it more efficient to calculate the indexes. In the demo, I use it as a variable to store the direction of movement of the enemies. Perhaps it would have been clearer to store this information in another array.

>>Another how to put text?

Is that update_scoreboard is a function in C at low-level that writes the number below / right (how many enemies have you killed)? As you just have to show a character what I do is pass the 8 bytes that define the numeric character from the ROM to video memory. The ‘0’ starts at $ 3d80, so depending on the variable killed to show, I start at $ 3d80, $ 3d88, etc …

The destination (dst) is the video memory. Eye, to work well I have to take into account the shadow variable, so the starting byte can be $ 50de (page 5) or $ d0de (page 7). The latter is a loop that copies the 8 bytes to video memory. As the video memory is not linear, what I do is increase the dst pointer by $ 100 instead of one.

Antonio Villena
To animate the gate you have to use sprites [] in the frames that you have animated. If you do it in the same way as the Churrera, it would be like this:

The first 8 sprites (from 0 to 7) define the protagonist.
In games with an overhead view, 2 frames of animation are used, one for each direction: up, down, left and right.
In games with side-view, we have from 0 to 3 to walk to the right and from 4 to 7 to the left. The animation sequence is 0,1,2,1,0,1,2,1 … to walk and 3 to jump to the right. For the left is 4,5,6,5,4,5,6,5 … to walk and 7 to jump.

Antonio Villena
Okay. I’ve already had an eye on him. It seems good to me how you are structuring it. The only small change I would make is to put the map in the same folder as gfx (if you want to change the name). The reason is that map would only have one file and especially because when distributing your map it is much easier to have everything in a folder (to open a map with Tiled you need the .pngs).

As for the omission of the keys at the beginning, it can be shocking, but believe me, in the long run it increases the readability (the edition gets a little worse because of the commas). The important thing is that everything is perfectly indented.

The configurable parameters I have concentrated all in config.def (especially the most important). I have done this to make life easier for the user, otherwise I would have to change parameters in several files. 2 passes are made, step1 and step2. In each pass, some files are processed and others are created. Some of those that are created contain parameters for the assembler or main.c. to read. Some examples are the define.asm that creates step1, and the defmap.asm, defload.asm and define.h that create step2.

Files in assembler there are 2: engine.asm and loader.asm. The first is assembled 3 times (with engine0.asm, engine1.asm and engine2.asm for the 3 possible machines) and the second generates the loader. The charger is a little messy because everything comes compressed and you have to mount the memory map that comes in readme.html.

This is the most important thing if you need me to explain something else, ask.

Antonio Villena
The numbers4map files are for numbering the GenTmx tool levels. Try to uncomment the GenTmx line that is in the .bat phase (in your case make.sh) and observe the map.tmx with Tiled and you will notice. The file number4map.c generates the file numbers4map.ha from numbers4map.png. GenTmx.c only has the include of numbers4map.h. Neither main.c nor any other file related to the demo makes use of numbers4map.

In the demo, the character 8×8 of the character map of the ROM is read, starting from the $ 3D00 address of the ROM. In $ 3D00 is the character ascii 32 (space), in $ 3D08 the 33 (admiration) and so on up to $ 3D80 which is where the digits from 0 to 9 start, which are the ones that interest us.

I recommend you use the spectrum sources to have more RAM for your game. However if you decide to use your own sources, count on me to make the generating tool (from the .png) and a printchar routine in assembler. If you see it very necessary, we can include it in the engine, although it can be deactivated via directive in config.def in case people want to take advantage of RAM using the source of the spectrum. What do you think?

Antonio Villena
You can also change the border from C directly in the main.c with M_OUTP (0xfe, color). If you realize, I use it in the demo to know how much frame time the engine consumes, how much the C code and how much time I have left.

Antonio Villena
When changing the variable * screen, the change does not take place immediately (neither the screen is painted nor the tiles array is filled in), but the next frame must wait. But you can go ahead by writing the FRAME macro (you do not really go ahead because at the beginning there is a loop waiting for the frame to start). Another cleaner solution would have been to force the change of tiles by calling the decompressor routine to fill the table of attributes, but it is not worth the cycles that you save and keep in mind that the location of the routines is variable, it would have to do the same as with FRAME, INIT and EXIT.

These are most of the quotes that had significant info in them, there might be more that are added, but this is enough for now.


Author: andydansby

I'm a hobbyist coder working with the ZX Spectrum. Living in New York state near the Syracuse area. I grew up in Virgina. The first computer my parents bought for me was a Timex Sinclair 2068.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s