📜 ⬆️ ⬇️

256 bytes of intro "Springs" for the computer Vectrex

The decision to write something for Chaos Constructions came, as usual, quite suddenly (primarily because it was not obvious until the last moment whether it will take place this year or not). So, there was no time left to write anything more than work for the Tiny intro contest (256 bytes for any platform). This also determined the choice of the platform, since under Vectrex I already wrote a couple of years ago and it was easier to remember assembler 6809 than to study the next one.

What (among other things) I like about the demoscene is that when getting to work, you have no idea what you will end up with. Among several ideas of what to write, specifically this one was not exactly. Two were discarded because the image on the emulator and the real Vectrex was too different - after each build it was impossible to upload all this into the ROM emulator and poke it into Vectrex to see what happened.

I began to implement the third idea, but already in the process I saw that it was too difficult to do such a thing in 256 bytes. But, in the process, something there went wrong and reminded the spring. This is the idea that I eventually developed:
')


I will not describe here how to program under Vectrex, since I have already done this in detail in my article . I will only mention that the principle of image output from this computer is radically different from most others - it is a vector. Moreover, with some reservations, it is possible to display not only straight lines, but also curves (which, in fact, I took advantage of).

An important sign of a good demo is, in my opinion, the use of the advantages of the platform under which the work is written. Almost all computers have strengths - on some it is hardware scrolling, on others there is support for a large number of sprites, on the third - a powerful processor. In this case, it was possible to draw the “coils” of the spring not by calculating the coordinates of each point of the curve, as it would have to be done on other computers, but by the hardware: when the voltage on the DAC of the Y channel (vertical) increases, change the voltage at short equal intervals on the D / D channel X (horizontal), resulting in a curve similar to a sine wave. Moreover, for each subsequent “spring” the amplitude was different and, accordingly, they have a different width (“diameter”).

Obviously, the springs must be compressed, otherwise what kind of springs are these? "Compression" is provided by changing the voltage vertically. More precisely, by changing the difference between the voltage at the point where the beam starts drawing the spring (bottom) and the point where the spring ends (top).

However, by simply increasing and decreasing this difference, you will not get away with it - for springs in such a situation, a different compression rate is natural depending on the current stretch. And here one cannot do without computations ... It is clear that the processor 6809 does not have commands for calculating sines, and the sine table for a 256-byte intro is too much luxury. Fortunately, having rummaged through the source files of the Vectrex ROM, I found there a label at $ fc6d, perfect for this case:

RTRIGS FCB 0,25,50,74 SINE TABLE- 16 ANGLES/QUADRANT FCB 98,121,142,162 VALUES REPRESENT SINE*256 FCB 181,198,213,226 FCB 237,245,251,255 FCB 255,255,251,245 FCB 237,226,213,198 FCB 181,162,142,121 FCB 98,74,50,25 

The only thing that needed to be done was to bring the values ​​to the desired scale, dividing by 4 by two shifts to the right:

 lsra lsra 

As a result, the spring is compressed quite naturally, and at the same time it rises / falls according to the same law - with acceleration and deceleration.

Now the next problem - who cares about the only spring jumping in one place? So you won’t win a com, you don’t get likes. Springs should jump one after the other.
With horizontal movement, for example, everything is simple. It is enough to change the voltage in the X channel of the DAC evenly and everything will happen by itself - leaving behind the screen where the overflow occurs (for -127), the spring will automatically appear on the other side of the screen (+127). The situation is more complicated with the synchronism of jumps - springs in nature never keep up, they always have some out-of-sync jumps.

Since the state of the spring at any time is completely determined by the value selected from the table of sines, it is logical to store this value separately for each of the springs. We select the address in the RAM where we will store this business. But, first, you need to initialize this tablet initial values. And not any, so that in the procession was some order. We reserve a few bytes in the ROM, and then copy it into RAM:

 springs equ $C890 ; index in sine table for each spring ... ldu #springstmp ldx #springs lda #(3*3) jsr Move_Mem_a ; A - byte count, U - source, X - destination ... springstmp: db 15, 20, 25 

As it is easy to see, all this joy is very easy to throw out completely, simply by finding the address in the BIOS where there are three suitable bytes in a row. Initially, I did not think that I would manage with three springs, and then there was no time to remove it, and there was no point (everything got into 256 bytes).

The plate of sines is small, so if for each iteration of the standard Vectrex cycle “frame by frame” we take the next value, the springs will jump very quickly. Therefore, we take from the plate the following value not every iteration (but we draw something of course into each, otherwise it will blink):

 ldb ,x ;   b        ( ,    x) ... lda frames_c bita #$03 bne skipinc ;  incb ;      skipinc: stb ,x+ ;    b ,  .      x   

Even for beauty, we add a bright luminous dot to the tip of the spring - before turning off the beam, we slightly hold it there:

 ldb #$40 ; end dot brightness (20-30 is ok for release) repeat_dot: decb bne repeat_dot clr <VIA_shift_reg ; Blank beam in VIA shift register 

At the bottom we draw a line of "earth" (by the way, because drawing a straight line happens through the BIOS, you have to set the maximum scale. In the case of a curve, you do not need to set the scale, since we draw it completely "manually"):

 lda #$ff ;   sta <VIA_t1_cnt_lo ldd #(-60*256+(-54)) ; Y,X.       jsr Moveto_d ldd #(0*256+(127)) ; Y,X      jsr Draw_Line_d 

A lot of space also takes the inscription below. So, I decided to limit myself to an abbreviated name and an indication of the size. However, there was another reason. The fact is that due to, in many respects, the analog nature of Vectrex'a circuits, its specific instances are inherent in any kind of distortion. Specifically, in my opinion it is expressed in two things:

1. When outputting lines by BIOS procedures (raster symbols are simulated using dotted vectors), as the length of the string increases, it begins to tilt, so that somewhere after 10 characters it is difficult to parse something.

2. With a decrease in height, the spring begins to warp to the left. This is not “so conceived” - this is the problem of a specific instance of Vectrex. I asked the owner of the two other cars to shoot, what the intro looks like with him. It is easy to see that the difference is significant:



Although the sound in 256 byte intro is quite rare, if there is such an opportunity - it is a sin not to use it.

What good is the BIOS Vectrex - it contains not only a simple subroutine for playing primitive melodies, but also a few examples of the melodies themselves (ten or two bytes each). For a big demo, this of course cannot be used, but for 256 bytes the intro is a great “cherry on the cake”:

 ldu #$fe38 jsr Init_Music_chk ; Initialize the music ... ;  , : jsr Do_Sound 

I must say that, as a result, the code was far from perfect, for which I am a little ashamed given that the 6809 assembler is very powerful and pleasant, so it’s impossible to refer to it as a reason (as it could be done in the case of, say, with my previous work on Videopac, which was quite unpleasant for Intel 8048 programming). I believe that having experience in programming under 6809, it would be quite easy to reduce the current 255 bytes to 180-200.

A large number of registers, including 16-bit ones, save a lot of nerves and bytes. In this case, however, it is curious that the increase / multiplication of the register by one is only for a, b, and d. But for index ones (and u), it means that with normal programming, they increase by one as part of commands like lda, u +. Even add does not work with these registers. However, there is a way out. You can increase and decrease them by any number of bytes with commands like leau N, u

Source: https://habr.com/ru/post/336784/


All Articles