Ok. We reduced the world map draw by 20000 cycles, sounds good – but we still must reduce it by another 35000 cycles.
Such a thing cannot be done by doing little things – here we must change something substantial.
For confirmation I take a look at the profiling of Vide – and unsurprisingly the DrawTile() function uses 43500 cycles and within that 42600 cycles to draw our vectorlists of the Map (the stringlist optimizations were not done yet – as you see the current string takes about 9000 cycles – so we are better than described above – yeah!)
The world changer will be a different approach to drawing the tiles.
The fastest known functions to draw something is specific optimized draw code for each list. But this takes heaps and heaps of memory.
The next best thing are smartlists – while initially these also have a huge memory imprint, it does not grow with “usage”. So I will try to use smartlists for this – thing is these things are pure assembler – and for that a DIFFERENT assembler than the usual one which is used with GCC.
But! we have a very usefull tool at hand – VIDE!
- Vide can create smartlists from any vector drawing
- Vide can output these list as “runable” code, which means it is a ready to go vectrex binary with everything we need – in assembler
- Vide can translate the usual assi code (Kingswood compatible) to as6809 assembler code with 2 clicks on two buttons
(after a little bit of cleaning up – we only want the smartlist routines and the actual smartlist, not the vectrex header and not the main loop)
- these assembler sources can be copied into the “C” src directory and are automaticaly assembled and linked with the “C” program
- of course the passing rules of parameters must be used by your assembler function (but in this special case – there are none!)
things have to be done however in the current Vide version (I’ll try to fix this with the next).
a) the linker must be made aware of the DP register settings – otherwise it utters warnings or even errors. This means before the first function but WITHIN the area:
Must be inserted!
b) If you are lazy like me and do not properly prototype your assembler functions with the correct register usage settings – things might get ugly.
Since I AM lazy – I must save the “U” register (at least) when calling the assembler function – so at the start there must be a “pshs u” and at the end a “puls u”.
(Actually – with smartlist export there is one other problem – which I will probably fix with the next Vide version. The actual vectorlists generated look like:
db -$03, -$05, hi(SM_continue_d), lo(SM_continue_d)
db $00, $02, hi(SM_startDraw_d_y0), lo(SM_startDraw_d_y0)
The AS6809 can not cope with these “hi/lo” constructs the above lines must be written as:
Mountainlist db -$03, -$05 dw SM_continue_d db $00, $02 dw SM_startDraw_d_y0
For the time being this must be done manually)
Ok. Yeah. I get it. You think that was complicated.
Hm. I am so into Vide – and doing those things… once you have done them a few dozen times, it seems really easy!
Anyways… lets look what we have got now.
Changing ONLY the mountain printing from Draw_VLp to smartlist – saved us over 25000 cycles. THAT is a world changer!
Let us see – we started with about 85000 cycles, so far we have done:
- 8500 for “string” changes
- 10000 for “C” changes
- 25000 for “Mountain” changes
= 43500 so we display now with about 42000 cycles – we need to find at least another 12000 cycles. Lets move on!
Well … there is a very logical next step – updating the other world objects to smartlists. But as you can see from the above image – usually not really many of them are displayed… nonetheless – lets do that.
- 2000 for “other map” changes
Now… let us think about Vectrex Frogger. What changes did Vectrex Frogger bring into the Vectrex world?
Doing stuff within the “move” time of vectors!
The current draw part looks like:
As one can see there is a Moveto_d(), some code and than the drawing. The “some code” stuff can be done DURING the move.
Now we leave a little bit the comfortable “C” – “let us call a subroutine” attitude, and do it ourselfs.
I am not in the mood to do an actual piece of assembler code, since here “C” does its job very well. The same code as above with the “beginning” of a Moveto_d():
The idea is to finish the move at the last possible moment, to catch as many cycles as possible. For that to work out best – I plan to finish the move within the “DRAWTile()” function – right before calling the smartlist.
But as it turns out – this is not necessary!
See – Moves in vectrex relation are funny things… if you give them enough time, they finish moving on their own (timer driven). So – if you can ensure that always enough time passes – you do not NEED to concern yourself with finishing the move!
And as it turns out – in our case “C” is slow enough (once this works FOR us 🙂 ) – that the move is ALWAYS finished befor we call the smartlist!
Long story short:
- 4000 for “in Moveto()” changes
Now we refresh in und 29000 cycles – like shown in the first image!
Ahhh. Yes. You got me there. The math does not work out yet. We should do another 6000 cycles. But here I cheat. The other 6000 cycles were actually not optimized within the “world” display – but within “housekeeping”, the main loop and other things. I might mention them later. But the “pure” world display is now as optimized as I wanted it to be. It might be, that there are more things possible – but I reached my goal. The world displays with lucky number 42 in all cases UNDER 30000 cycles.
If you tell me a lucky number where that is not the case… I’ll happily go in search for more optimization of the world display, but for now I am done!
to be continued (the dungeon)