(For the first part look at: 20th-of-february 2019)
This time it is: “If you wait a little – you will be faster!”
Actually it is exactly the same topic and the same phenomenon as described above, but this time viewed from another angle.
You remember, last time it was (see image):
The effect of the “open end” vectors seem to be caused by different reaction times of the ~RAMP signal and the ~BLANK signal.
The differences in the gaps “length” was due to different cycle values when entering the wait that finished every move or vector draw.
Interlude: How to Draw a line or Move to a position
Move to a position and drawing a line is actually exactly same same thing – nearly. The only difference is that with the one, you switch the light “ON” and with the other you switch the light “OFF”. So these two functionalities are programming wise nearly identical.
Each of those functions has the following:
a) setup before actually drawing:
set the time (scale) how long the movement should be done
b) give parameters to function:
set the strength (or speed) for the horizontal and vertical direction to move the “cursor” with (y,x position)
c) start move (or draw)
d) wait in a busy loop, till the time for movement has finished
Programming “tight” vectrex programs often times calls for optimization. One such optimization is to use the above busy loop for some additional calculations, that are certain to be finished before the time has run out. That way the busy loop has less time to be busy and the before “wasted” time is put to good use by doing some needed calculations.
Often time when coding I thus do not use the BIOS MoveTo_d function, but I use two macros instead, namely:
Both macros correspond to above mentioned sections c) and d).
I will not go further into the programming of those… except:
LDB #$40 ; 
BITB <VIA_int_flags ; 
BEQ waitLoop\? ; 
This is the busy loop. It waits till the sixth bit ($40) of the VIA interrupt flag register is set. This happens, when the timer T1 runs out, the timer contains the time (or scale) for how long the moving (drawing) should continue. Once the interrupt flag is set, the moving (drawing) is done – and the program leaves the busy loop and can continue.
In the following I will show with an example the strange effect this wait loop can have and how you can wait a little bit to gain some cycles :-).
For one reason or another I was trying out (again) to display a raster image, this I will use as an example, look at following image:
This is an image of text, with the complete height being 38 lines. For each line I position the cursor at the start of the line. In this special case these are 38 MoveTo_d, each with the same scale, the scale is $60.
This means each positioning takes $60 + x cycles to do (x being the time needed for above mentioned a) and b) ).
The MoveTo_d I realized with above two macro definitions to have them seperated.
The actual time I spent in the busy loop is more than $50 cycles, I am not discussing how to use these cycles now… but I’ll show a different effect.
Following macros I defined for exact wait cycles:
nop ; wait 2 cycles
brn 0 ; wait 3 cycles
tfr a,a ; wait 6 cycles
pshs cc ; wait 12 cycles
In a series of test runs, I added right befor the MY_MOVE_TO_B_END above defined wait macors. The overall execution cycle values are:
- WAIT 0: 32205 cycles
- WAIT 2: 32279 cycles
- WAIT 3: 32316 cycles maximum
- WAIT 4: 32094 cycles minimum
- WAIT 5: 32131 cycles
- WAIT 6: 32168 cycles
- WAIT 7: 32205 cycles
- WAIT 8: 32242 cycles
- WAIT 9: 32279 cycles
- WAIT 10: 32316 cycles
- WAIT 11: 32094 cycles
You can see (as with the other mystery), that the values repeat after a 7 cycle gap, this is due to the fact, that the busy loop takes exactly 7 cycles per “round”.
The difference in cycles is due to the fact, that the actual compare to the interrupt flag is only done in ONE cycle, if the interrupt flag is set just after the compare… in the worst case you have to wait (waste) additional 6 cycles in order for you to actually REALIZE the interrupt flag was set!
If you are crazy about optimization – you can use this knowledge to your advantage!
In many games following facts are common:
- all (many) moves use the same scale
- there are many objects on the screen
- the cycles between
are fixed and not dynamic
If above is true you can with a simple test run (above wait macros) determin your own personal “best” wait, and save up to 6 cycles per move.
In a crowded game that might be 50 objects – meaning up to 300 cycles saved!
For a really tight optimization – this is a nice addition to cycles being saved… small things add up :-).