If you played VPatrol – you know what that is.
I personally think it represents a glider taken from a TV series called “Space: 1999” (German: “Mondbasis Alpha 1”).
That glider is part of the calibration routine within VPatrol.
You might say “so what”?
I tell you what – that is one single vectorlist consisting of over 60 vectors (and moves). There is no synchronizing done – no return to zero or anything else. That glider is drawn in one go!
Do you notice any drift?
If you did your calibration right – you don’t! That is the point! Usually if you draw more than say 10-15 vectors in one go – you will see all kinds of drift madness. I will not go into the calibration again – this time I’d like to take a look at the drawing routines themselves.
The routines Kristof uses I believe he calls “SmartList” for now I will keep that name. The routines themselves are not sooo much different than the ones from Thomas – and my Release routines might be also viewed as distant relatives. Nonetheless I never really investigated Thomas routines to closely and on this blog I never mentioned the object handling in Release – so for now I will present you the SmartList (or partials anyway).
Since I do not have the original sources – I must use my own naming conventions – please bear with me…
Following is the “main” section of a program that does the calibration (which is neccessary) and displays the glider:
Basically the first 9 lines ask the joystick for left/right and adjust the calibration value. Than there is the WaitRecal to ensure 50Hz, a call to our “calibrationZero” which goes to zero and sets DAC offset value. Than a “bad” slow MoveTo_d so the image of the glider is centered.
Than the glider is displayed. The address of the vectorlist loaded to register U and the “drawSmart” routine is called (which only does a pulu d,pc – Ha! This DOES look like Release after all 🙂 ).
Now the fun part!
What you see is a list of register A, B values and a “subroutine” call. To keep the list in “db” values I used in the above representation hi(), lo(). It might have been better to do something like:
db 10,20; y, x value dw SM_startDraw_d
The data/list representation is “ultra” flexible. Basically its a string of subroutines which are always called with two parameters. Each subroutine is “closed” with another PULU a,b,pc – and automatically the values are loaded and the next subroutine is called – for the cost of mere 9 cycles.
E.g. the first subroutine “SM_setScale” is called with register A = 0, and register B = SPRITE_SCALE. The complete subroutine looks like:
SM_setScale: stb <VIA_t1_cnt_lo pulu a,b,pc
Thats all. But you could do more – … it could be an init routine of sorts, it could set the intensity or or or…
The subroutines Kristof wrote are the “smartest” things of this collection of routines:
This “moves” to the next location (y,x position given in before pulled a,b). The “clever” part here is, that the shift register is NOT changed. This
a) saves cycles
b) the subroutine can be used for a “continued” move or a “continued” draw.
The above one “starts” a move, it is ensured that Blank is 0!
The obvious counterpart is “SM_startDraw_d”.
But there is more “cleverness”:
Here you see reference to “SM_continue_newY_eq_oldX” that routine “knows” that the new y value is the same as the old x value – which means that DAC need not be set again, only the MUX (saving precious cycles).
If two consecutive moves/draws are exactly the same – you can call a “double” function – which in general only enables ramp a second time (thru timer 1).
Notice the “bra” above seems a bit “stupid” – but there are timing issues. Timer1 must expire before setting it again, otherwise the full vector is not drawn – so if you encounter some “meaningless” code (like brn, or tfr a,a …) – that is usually timing related!
… and so on…
To generate “SmartLists” I guess Kristof has written a special program that disects vectorlists and examines them closely. Might do that in Vide some day too! 🙂
All “SmartList” functions I encountered seem to work “out of the box” up to a scale of 9 (perhaps 10). Above that scale the routines have timing issues.
This has todo with above mentioned Timer1 which must be allowed to expire before doing anything new. Within all SmartList functions there is not one Wait loop or interrupt flag interrogating – the timer is ALWAYS expired before the next relevant changes are made! (Which again reminds me of my own “fast draw” routines – I usually also do not have idle loops).
If you happen to use Kristof functions and want to use larger scales than “9” you have to change the code.
The changes are actually quite simple – after each “clr <VIA_t1_cnt_hi” you can place a macro call to something like:
SPRITE_SCALE = $20 ADD_NOPS macro if SPRITE_SCALE>9 nop (SPRITE_SCALE-9)/2 endif endm
That macro “inserts” the right amount of nop (no operation – 2 cycles idle…) into the routines. The above image I took from the vectrex is the glider drawn with a scale of $20.
Calibration still works – even with that “high” scale!
Well, you might think – why bother this seems really complicated…
a) No – it isn’t. Perhaps you have to resolve some knots in your brain and think a bit differently (perhaps a bit OO) – but this drawing is really efficient!
b) Speed – the routines if all “cleverness” is used are damn fast, drawing the glider with scale 9:
Draw_VL_Mode: 7803 cycles
Draw_VLp: 4825 cycles
drawSmart: 2122 cycles