Example: Lightpen

For the lightpen no "Code Generation" was done, since any generated code would have been an extensive example on its own.

Instead I provide an example in form of a "code snippet" within codi. (see:
codelib/Snippets/Malban/Lightpen/LightpenExample.asm
and
codelib/Snippets/Malban/Lightpen/LightpenSubroutines.i
)

Much of the example is reused code found in the Artmaster binary and the great disassembly of Fred Taft.

I enhanced his disassembly in two ways:

  1. added further comments

  2. extracted a couple of subroutines, which can be used "out of the box" without sorting out to much stuff

Anyone interested in programming lighpen stuff should find it (I hope) to be quite easy to get going.

I didn't bother to provide examples for lightpen usage in port 0, I can't really seem to find much use for it, although the routines in general should be nearly the same. Further writings about lightpen in this documentation always assumes lightpen in port 1.

In general

The main (and actually - ONLY) communication that is going on between the lightpen and a vectrex is by whether "button 4" of joyport 1 is pressed or not. The lightpen internally reacts (how else could it be) on light. If the light is switched on the button is active (I say active here, in reality the state of the button goes low, but that is sort of confusing, lets just say light = active), if the light is switched off - the button is not active. The switching is done "lightning" fast. If you use your usual vectrex 50Hz display, the button is switched on/off 50 times per second, the "glow" of the vectors is in this case negligible.

Also, button four of the joytickport 1 is connected to the CA1 line of VIA, this enables us to very easily check whether the lightpen is active - or not (we do not have to check the PSG all the time).

If the lightpen is active, CA1 will be 1 - true, or whatever you want to call it :-). This enables us to use the interruptflags of VIA to check whether the lightpen saw some light or not.

The interruptflag is usually configured that it is set upon the lightpen going from inactive to active.

  1. the IFR must be reset befor an interrupt can occur again

  2. that lightpen must be inactive befor it goes active again in order for an interrupt to occur

Checking lightpen for a vector

Remembering that, the general strategy to check for lightpen is:

This is really straight forward.

It gets more complicated, when you do not have a vector that you want to react upon, like finding a lightpen which was placed on an empty screen, or if you want to use your lightpen to "drag" a vector around the screen.

In this cases you must think a bit around the corner...

Checking lightpen for a "move"/empty screen

All strategies come down to using the above strategy. You can not check for light, without light! Therefor the two strategies the old artmasters came up with are:
(you are invited to come up with your own...)

Note on Interrupt:
Although none of my VIA 6522 documentation describes this - the routines described below clear the Interrupt flag with
"CLR         VIA_int_flags"
this obviously works ok though ...

Example routines

The provided example shows four different lightpen "situations":

The code is well structed and documented, I will not document it here further.

The example main program includes a set of lightpen routines, which can be found in the above described file:
codelib/Snippets/Malban/Lightpen/LightpenSubroutines.i

That file includes a set of "public" routines, which can be "normally" used, and some routines which I like to describe as "private". Which a "user" not neccesarily must use, but which support the public routines.

Following public routines are available:

print_with_pick_check

This routine is very much like the ordinary Print_Str routine the BIOS offers.

As input a pointer in U Register is expected which points to a string structure consisting of:
DB height, width
DB ypos, xpos
DB "SOME TEXT", $80

If a lightpen pick occured while printing the string, the variable "lightpen_pick" ($C89E) will be set to 2 if no pick occured it will be 0.

draw_vector_with_pick_check

This routine is very much like the ordinary Draw_Line_d routine the BIOS offers.

It draws a vector from the current position, using the current scale to the delta coordinates given in register D. On return register A is set to 2 if a lightpen pick occured and if no pick occured it will be 0.

search_screen_for_lightpen

(This method uses 6 bytes of RAM, see documentation in source code)

This routine implements the above mentioned "scanning". After a call register A will be $ff if a lightpen pick was found or 0 if not. If a pick was found register X contains the location (scale factor $ff) as y, x.

check_point_move

(This method uses 12 bytes of RAM, see documentation in source code)

This routine implements the above mentioned "webbing".

This routine expects as input parameters in register X the "point" that might be moved, and in register A a flag whether the "point" was found by the lightpen the last time it was checked.

The return of the method is the same as the input:

After a call register A will be $ff if a lightpen pick was found or 0 if not. If a pick was found register X contains the location (scale factor $ff) as y, x.



Lightpen example 1




Lightpen example 2




Lightpen example 3