░▒▓ (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