

        °±² (CEVS) Cross-Eyed Viking Solutions ²±°
        GETE (Graphics Effect Test Engine) 1.0 - Real Mode.
        Lorne Kirkland Chartier (1996) - public domain.
        -----------------------------------------------

        Many programmers develop quick and messy little modules to test new
        graphic routines.  The coder may not take the time to polish and
        release the routine due to being to busy.  I thought I would take a
        little time to develop a "test bench" that would handle most of the
        ugliness of developing and testing new graphics routines.  The idea
        is you simply provide the routine and let the program handle all
        the hassles of the interface, timing, etc...  It isn't particularly
        fancy but gets the job done.  Hopefully this will encourage coders
        to release more routine source as the polished engine is already
        taken care of.


        Features:

        - 100% assembly, extremely compact and fast
        - high-resolution timing of effect only, good for optimizing
        - real-time resizable effect buffer
        - startup fill states: 1 random, 8 pattern, 1 256c PCX
        - a few lamer effects to give you an idea how to use it


        Code for / Demonstrating:

        - calling effects via jump tables
        - high-resolution timing
        - interrupt driven keyboard processing
        - modify executable size internally & allocate dos memory
        - optimized sample effects (use as a template for own routines)
        - pcx decoding / encoding


        License / Usage
        ---------------

        This code is public domain, free for use without restriction.
        However, if you find the program useful and develop some effects of
        your own please consider releasing your sources and emailing me a
        copy:

            Author: Lorne Chartier
            I-NET:  jamesg@nucleus.com

        Thanks muchly...


        Jump Tables / Adding New Routines
        ---------------------------------

        The routines are called via a jump table (see JUMP_Tbl structure).
        This table includes the routine far address, description far
        address, and some flags which affect the way the routine is called
        or functions.  When a routine is called the previously displayed
        frame is passed as frame 1 and your routine is expected to fill in
        frame 2.  The flags can affect this is as follows:

        lsb/01h - do extra line:  This flag is essentially only useful for
        fire routines.  I can't stand that awful white line at the bottom
        of those routines.  Setting this flag will tell your fire routine
        that the buffer is one row longer than what will be displayed and
        therefore the line will be hidden.  Note that the extra line was
        allocated for when the alocmem() routine was called (+ 1).

        lsb/02h - copy frame 1 to frame 2:  Not all routines absolutely
        require a previous history frame from which to function.  Plasmas
        are a good example of this as they usually generate the next frame
        based on memory tables.  If you make them conform to the frame 1 ->
        frame 2 method then they might run slower than possible.  Setting
        this flag makes the engine copy frame 1 -> frame 2 before calling
        your routine (and is not part of the timing) so your routine can
        work with frame 2 only (this could free up registers, etc...).

        lsb/04h - no frame swap:  Normally a routine uses frame 1, applies
        its affect and writes the result to frame 2.  The program displays
        frame 2 and swaps the frame pointers so that the frame is frame 1
        for the routine's next call (thus creating a continuous motion).
        This is not always desirable for all routines.  Setting this flag
        ensures that frame 1 is never swapped and therefore is a perfect
        copy of the original from which to create the next frame.  This is
        useful for cases where cumulative rounding errors or data loss
        would result in an increasingly degraded output frame.  Bitmap
        rotation is a good example of where it is always best to work with
        the original bitmap.

        lsb/08h - clear borders:  Effects like cellular automata generally
        require counting a pixel's neighbours.  To make the code simpler
        you generally only perform calculations for all pixels that are at
        least one pixel away from any border.  Other effects may leave
        various pixels in this "buffer zone" which will show up as garbage
        when flipping from another effect to cellular automata effects.
        Setting this flag will clear the border "buffer zone" when the
        effect is switched to or the buffer is resized.

        So you basically only need to add the routine to the appropriate
        jump table (setting the flags as appropriate) and recompile.  The
        assembler automatically calculates the number of table entries.

        The calling code pushes the following parameters on the stack:

                src     dword   : 32-bit (seg:off) far ptr of src buffer
                dest    dword   : 32-bit (seg:off) far ptr of dest buffer
                bufw    word    : 16-bit buffer width
                bufd    word    : 16-bit buffer depth

        The routine must exit with a "ret 12" or just copy one of the other
        effects using the pascal calling parameters instead (which handles
        the parameter details for you) to use as a template.


        Palettes
        --------

        Color 0 is assumed to be off for many effects (essential for
        cellular automata, etc...).  Palette cycling does not cycle through
        color 0.  When a palette is set, the program searches the palette
        for the greatest contrasting color to color 0.  This is the display
        color that is used for the screen status lines and help screen.  If
        you cycle the palette it will change the display color as well,
        possibly to an unreadable color.  Use F2 to recalculate greatest
        contrasting color.  The cycle direction will show as a + or - in
        the lower right hand corner or nothing if cycling is off.

        In addition, pressing [alt]-[1..9] will load the 6-bit palette
        GETE#.PAL where # is [1..9].  See Matt Pritchard's MODEX105.ZIP for
        a completely free 6-bit palette editor.


        PCX Support
        -----------

        GETE allows loading a single PCX file called GETE.PCX into the
        active buffer.  The PCX file must be 320 x 200 or less in size and
        will only load correctly (ie: not garbled) into a buffer that
        matches the dimensions.  Generally this is only good for doing full
        screen effects on a bitmap.  Use F3 to toggle whether or not to
        make the PCX palette active upon PCX load.  The palette load status
        will show as a P in the lower right corner if on or nothing if off.

        The current screen can be saved to a PCX file at any time using the
        print screen key.  It will have the screen as SHOTxxx.PCX where xxx
        is a numeric value starting at 0 that does not overwrite any
        existing screen shots.


        Timing
        ------

        I use the high resolution timer to time only the call to the
        effect.  All the other maintenance like screen writes and keyboard
        checking is not timed.  This way you get to see exactly how fast
        your routine only is running (all the other stuff you need to do in
        your own program but the time will be essentially fixed - you need
        to squeeze speed out of your effect).  Anytime you size the buffer,
        switch effects or do a fill the frame/generation counter and timing
        is set back to 0.

        I was too lazy to show you a second count upon exit it is not that
        important - get the initial count, optimize away and then check the
        % of speed increase.  The count returned is high resolution ticks
        and you can convert it to seconds by dividing by the constant in
        TIMER.INC.


        Coding / Additions
        ------------------

        This 286 / real mode version reminds me of why I gave up on both
        286 and real mode support.  Segmentation is a serious pain in the
        arse.  386 / pmode allows optimizations including dword aligning
        every buffer row, buffer row start table to kill multiplications,
        386+ instructions, read / write dwords, easy access to global math
        tables, and many more enhancements.

        Some suggested improvements include:

        - global 8.8 fixed point math support with sin/cos tables
        - machine independant adjustable frame delay


