Custom Graphics Engine
Creating Virtual Graphics
Creating Virtual Graphics Masks

At runtime you can create new graphics from the graphics in your CSBgraphics.dat.  The code word for doing this is 'CreateVirtualGraphic'.  There are several reasons you might want to do such a thing.
In any of these cases there are drawbacks to having multiple graphics in CSBgraphics.dat:
'CreateVirtualGraphic' takes two 'graphic IDs'.  The first is the source (existing) graphic ID and the second is the destination (virtual) graphic ID.  If the destination graphic ID already exists then nothing is done.  This means that your code does not need to worry about doing the operation 'one-time-only'.  Your code can be written to create the Virtual Graphic every time and the runtime engine will see that it has already been done and skip the operation.

The Virtual Graphic is created from the source graphic using an 'affine transformation'.  Both the source and the destination are treated as being in the shape of a torus so that there can be no problem with coordinates out of bounds.  Each point in the Virtual Graphic is copied from a point in the source graphic.  The equations for the coordinates are:

Sx = ( Cxx * Vx + Cxy * Vy + Cxc + 16 ) / 32
Sy = ( Cyx * Vx + Cyy * Vy + Cyc + 16 ) / 32

Sx, Sy = The coordinates of the source pixel to be copied to the Virtual Graphic pixel.  Integers.
Vx, Vy = The coordinates of the destination pixel in the Virtual Graphic.  Integers
Cxx, Cxy, etc. are the elements of the transformation matrix.  Integers.
The constants '32' and '16' are to make things work more like real numbers rather than integers and to round to the nearest source pixel.

The constants Cxx, Cxy, etc are contained in a Mask fetched from the CSBgraphics.dat.  We will refer to this mask as the 'Virtual Graphic Mask'.  The mask contains six 32-bit numbers in the following order:
0 - Cxx
1 - Cxy
2 - Cxc
3 - Cyx
4 - Cyy
5 - Cyc

Also, the algorithm works on a rectangular section of the source graphic.  So it needs to known the location and size of a rectangle within the source graphic.  In addition, it needs to know the size of the destination graphic.  These parameters are contained in the same Mask.  The parameters are as follows:
6 - x-coordinate of left side of source rectangle
7 - y-coordinate of top of source rectangle.
8 - width of source rectangle
9 - height of source rectangle
10 - width of Virtual Graphic (multiple of 16)
11 - height of Virtual Graphic

And, of course, the Source Graphic ID and Virtual Graphic ID are needed and are included in the call.
So the word to create a Virtual Graphic is defined as:

CreateVirtualGraphic (
sourceGraphicID virtualGraphicID maskID  maskNumber . . . )


Virtual Masks

Virtual masks can be created in a manner similar to that for creating Virtual Graphics.  The only person who actually used this capability asked that the parameters be drawn from the stack rather than from other Masks so that he could easily compute the parameters from the sizes of the masks and pictures that he was using.  So the parameters are handled quite differently.  Also, you are expected to create a virtual mask once and only once.  If you attempt to create a mask that already exists a message box with an error message will appear at runtime.  You can easily determine if a virtual mask already exists by using the following word:

NeedVirtualMask?  ( maskid maskNumber -- flag) // flag will be set true if the mask does not already exist.

A virtual mask is created using the following word:

CreateVirtualMask ( oldMaskID oldMaskNumber <newHeader> <affineParameters> newMaskID newMaskNumber -- )

The <newHeader> is the six parameters to put into the new mask's header.  The <affineParameters> are the first six parameters listed above for creating a virtual graphic.  So, all-in-all, sixteen integer parameters need to be provided.  If you want to put the six parameters into the CSBgraphics.dat file then you can put them into a mask and then fetch them to the stack using 'GetMaskHeader'.  Likewise for the six <newHeader> parameters.  Or you can compute them at runtime.

Virtual Affine Masks

You can also create 'Affine Masks' at runtime.  First you use 'NeedVirtualMask' to make sure that it does not already exist.  Just like 'Virtual Masks'.  Then you supply the 12 parameters needed for the mask plus the ID an number of the mask and us the word 'CreateVirtualAffineMask':

CreateVirtualAffineMask ( Cxx Cxy Cxc Cyx Cyy Cyc srcX srcY srcWidth srcHeight dstWidth dstHeight MaskID mask# . . . )

The dstWidth must be a multiple of 16.

The long list of parameters can be filled easily if you have masks that already exist in the file that can be copied with 'GetMaskHeader'.