1st of March, from Centipede to Shongololo…

I pondered a bit whether to write a blog entry for this. But since the other possible Vectrex “work” would be getting on with Vectorblade – I’ll write a few sentences (Buhuuuu).

On FB the question came up, whether a decent Centipede clone exists/could be done. There were some pros/cons – and I remembered last year the 70/100 (blog entry 1/ blog entry 2) sprite thingy I wrote about – and challengingly exclaimed:

“Pretty sure if someone was dead serious about it – something decent could be done…”

Well – decent maybe/yes – but probably not quite a centipede. I did a little counting, the “shroom resolution” of the original is about 30×30, which would in extreme cases (full screen) be 900 mushrooms.

Vectrex can’t do that. Vectrex doesn’t even have enough RAM to store position information, let alone being fast enough to display that many (or even half, or quarter or … a tenth).

Nonetheless I had the 70/100 code lying around – and started experimenting.

My “final” experiment can be seen in the youtube video:

The “shroom resolution” is 16×16 ( -> about the quarter of centipede).

I changed the “70” demo in about 2 hours to display above. The collision detection “pede <-> shroom” is realized using a bitmap of 16×16 bits. Call me stupid, but for that to work in (hopefully) all cases correctly took me 3 times as long :-). (it is NOT a linear bitmap, but actually “scrambled” around using signed 4 bit position information) – but it can be calculated and each pede part only checks ONCE per round, not with each shroom, so in the end it is quite performant – I think…

I have given the source of the “demo” to a fellow vectrexian who intends to build a full game, since I am not inclined to work on that any further (I still intend to finish Vecctorblade 🙂 ).

I will also make my last source version available here (see bottom of article to download), since I find the used graphic routines “interesting” and I hope others might do likewise.

I did them over a year ago, but actually never looked back. But seeing the graphics again – I remembered…

Yes, the screen is dirty, yes its not 100% in focus… But the thing is – look at the “sprites”.

It looks like they were drawn in ONE stroke, there is no vector 1 start here, end here, start next vector. The “corners” are all a little bit “round”… and the graphics actually look fantastic on a vectrex (well, my humble opinion).

Thing is, in order to draw as fast as possible I (as usual) wrote my own routines. But this time I wrote “special” routines which actually are “technically” different from the BIOS routines.

The routines are “direct draw” routines in the sense, that I did not write them as:

  • subroutines – the vectors are drawn “in code”
  • and each drawn vector is thus realized as a “macro”

The actual “drawing” of the head of a centipede looks like:

INIT_DRAW_6_MOVE_END  ( ( BIG_SIDE ) *256 + (000) )   
LINE_DRAW_6_x ( ( BIG_SIDE )*256 + ( 000) )
LINE_DRAW_6_x ( (-SMALL_SIDE )*256 + (-BIG_SIDE) )
LINE_DRAW_6_x ( (-SMALL_SIDE )*256 + ( BIG_SIDE) )
LINE_DRAW_6_x ( (-SMALL_SIDE )*256 + (-BIG_SIDE) )
LINE_DRAW_6_x ( (-SMALL_SIDE )*256 + ( BIG_SIDE) )
LINE_DRAW_6_x ( ( 000 )*256 + ( SMALL_SIDE) )
LINE_DRAW_6_x ( ( BIG_SIDE )*256 + ( SMALL_SIDE) )
LINE_DRAW_6_x ( ( BIG_SIDE )*256 + (-SMALL_SIDE) )
LINE_DRAW_6_x ( ( 000 )*256 + (-SMALL_SIDE) )
DEINIT_DRAW_6

(BIG_SIDE being 80 and SMALL_SIDE being 40)

The first macro “ends” the move which is still ongoing and starts outputting the first vector. Than a couple of draws happen and the list is finalized with a deinit.

If there are not many different sprites (animations… many different “creatures”) this is a very “time” efficient way to draw (which needs a little bit more memory).

Anyway with this kind of drawing you can actually do 70-80 sprites in 50Hz without to much of a problem (game logic pending 🙂 ).

Init

This is the init macro, it:

  • first sets the scale factor (6)
  • pre loads register u with the X size of the vector (in its lo part) and a correct value to write to the VIA_B register (a 1 in its hi part)
  • register A is cleared and kept for all following “macro calls” at value 0
  • end the moving (wait for interrupt flag to set)
  • sets y size to register b
  • “clears” VIA_B -> so the DAC value will go to the y integrators
  • and writes the Y value to DAC
  • Notice: I did intentionaly not do a STD, this is because again some rare vectrex exist which do not like that (see 3 blog entries back)
  • now we must “wait” four cycles, otherwise some vectrex will get crazy (this also depends on the “old” value in y integrators)
  • the wait is realized with pre loading register B with the correct VIA_CNTL value to switch blank off (“$ee”) and a NOP, the sum of both is 4 cycles
  • write the preloaded register U to VIA_B which sets both the MUX to disable (VIA_B) and puts the X value to VIA_A (since U is a 16bit value)
  • than the timer is started (value 0 which is now ALWAYS in Reg A is put into VIA_T1_hi)
  • and disable the BLANK by writing the above preloaded value to the VIA_CNTL register
  • now the first vector is being drawn!
  • WE DO NOT USE SHIFT, the VIA_AUX must in advance be set to $80! (switch off SHIFT register)

Draw

  • the complete DRAW of a vector is realized in only 6 lines which use alltogether 22 cycles. That is FAST!
  • I will not describe the complete lines -> there are comments (and is a repetition of the above also)
  • BUT: between line 47 and line 59 there SHOULD be 4 cycles wait, as described in above comment. In “my” special case I think (hope) they are NOT necessary. See, the wait cycles are needed, when the Y-Integrator values leaps from “huge” negative values to “quite huge” positive values. The largest positive and negative values I use are +/- 80. I hope for these “small” largest values no waits are needed. (Jürgen/Thomas/Nathan… if you have time and inclined to – please test – you are the ones I know to have these “rare” vectrex)
  • Notice also: The BLANK is never ENABLED during the entire drawing – really the vectors are drawn in one stroke!

Deinit

  • consists mainly of “waiting for the last line to be finished”. Here are “5” NOP used. If in the “end” there is time enough for all drawings, than this can be set to 6 or 7. 5 are OK, but you can see a very small gap at the end of each vector. Due to drift this will never be fully closed, but using a higher NOP count will close it a tiny little bit more.
  • I “preset” the scale value in anticipation of the next “move” …
  • and finally switch BLANK on and ZERO on (light off – beam to zero position)
  • and – again I wait a little bit, since the next object with its move is right around the corner. If we do not wait here for at least 14 cycles, the zeroing will not be complete – and the next move will be slightly off.

That was the current stage of “Shongololo” from my side.

Here my last source: http://vectrex.malban.de/tmp/Shongololo.zip (50kb – Vide project)

Tagged on: ,

6 thoughts on “1st of March, from Centipede to Shongololo…

  1. Savvas

    Greetings,

    I’ve been looking for such drawing tips for a long time so your post is extremely helpful.

    There appears to be a problem with the zip file – seems to be corrupted as only 1.5 Kb is download at each attempt. Any chance of re-uploading?

    1. Malban Post author

      Thx.

      Note:
      a) The drawing routines do not work perfectly with “cranky” Vectrex (see other blog entries what I mean by that)
      b) Dunno why I removed the ZIP… but if you load the latest VIDE version, the Shongololo project is in the “Vide/projects/” folder

      Regards

  2. Brandon

    Thank you again for posting this. I took a break and came back to it. It is a conceptually rich example for the amateur Vectrex programmer.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.