\input texinfo   @c -*-texinfo-*-

@c Use A4 paper - If you don't like that, remove the following 3 lines.
@iftex
@afourpaper
@end iftex

@setfilename xaos.info
@settitle An fast realtime interactive fractal zoomer
@dircategory Graphics
@direntry 
 * XaoS: (xaos).                 The fast realtime interactive fractal zoomer
@end direntry


@ifinfo
@copyright{} 1997 Jan Hubicka

Permission is granted to make and distribute verbatim
copies of this manual provided the copyright notice and
this permission notice are preserved on all copies.

@end ifinfo

@c %**end of header

@set VERSION    3.0
@set DATE       Mar 2, 1997

@titlepage

@title{XaoS @value{VERSION}}
@subtitle{An fast realtime fractal zoomer}
@subtitle{Users and hackers manual}

@author{Jan Hubi@v cka}
@tex
Dukelsk\'ych bojovn\'\i ku 1944 
@end tex
@*
390 03 T@'abor @*
Czech Republic

Email: @code{hubicka@@paru.cas.cz}

@value{DATE}

@page
@vskip 0pt plus 1filll
@vskip 0pt plus 1filll

@copyright{} 1997 @tex Jan Hubi\v cka 
@end tex

Permission is granted to make and distribute verbatim
copies of this manual provided the copyright notice and
this permission notice are preserved on all copies.

@end titlepage

@c %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@node   Top,    Overview,       (dir),  (dir)

@ifinfo
@top XaoS @value{VERSION}
@flushright 1.0
An realtime interactive fractal zoomer
@value{DATE}
@end flushright
@end ifinfo


@menu
* Overview::		What does this software do then ?
* User::		User's guide
* Hacker::		Hacker's guide
@end menu


@c %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@node Overview, User , Top, Top

@chapter Overview
@menu
* Why?::		Why yet another fractal generator?
* What?::		What does this software do then?
* History::		How this all started?
@end menu

@node Why?, What?, Overview, Overview
@section Why yet another fractal generator?


We decided to make XaoS, because all fractal browsers we know needs
long time to calculate every image. You may browse nice images
generated by them but real impression from fractal---they self
similarity and possible infinite zooming into nice part of fractals
can be seen only in animation. There are many programs available that
makes nice animations but they takes long time to calculate and lots
of space on disc. Most of animations are quite ugly because their
authors can't see it without many hours of calculations.

Natural question is: it is possible to generate such animation in
realtime? Ansver was negative for many years, since Mandelbrot set is
very computational expensive. Thinks are changing. Today's computer
are fast enought to calculate aprox. 1000 pixels per frame. It is enought
for very low resolution animation (30x30). Several programs doing that
are available. But 30x30 animation still looks quite ugly. To make
animation nice you need at least 320x200 pixels. And thats 65 times more!
One possibility is wait until computers will be fast enought, but
it should take many years and then 320x200 animations will be obsolette
and everyone will want 1024x768 resolution instead.

We found special algorithm that saves up to 99.98% of calculations during
zooming by reusing pixels already caluclated in previous frames. There were
some programs doing similiar trick before but we don't know about any able
to do zooming interactivly in same or higher speed than XaoS does. Many
other tricks was later implemented into XaoS to archieve higher framerate.
Now XaoS does up to 120 frames per second at 120Mhz pentium in fullscreen 320x200
animation and calculates at the avearge 160 (0.24%) pixels per frame.
This makes XaoS fast enought to archeieve primary goal---realtime animation,
but there is still many places for improvement, since more complex fractals,
higher resolutions, or slower computers still brings many problems.

@c %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@node What?, History, Why?, Overview
@comment  node-name,  next,      previous,  up
@section What does this software do then ?

XaoS is an realtime interactive fractal zoomer. This means that it lets you
zoom smoothly into place you choose without many hours of calculation required
by most of other fractal generators. It now has also many other features,
like 9 different fractal types, autopilot, special coloring modes, support
for various bit depths (8bpp, truecolor, hicolor and realcolor), random
palette generation, color cycling etc...

@c %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@node History, , What?, Overview
@section How this all started

This section is still under development. Sorry :)

@c %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@node User, Hacker, Overview, Top
@chapter User's guide

This charapter contains documentation for XaoS's users. It contains maninly
thinks that are too long to describe in help or tutorials. So it is targeted
for advanced users.
@menu
* format::		XaoS's file format description
@end menu

@node format, ,User ,User
@section XaoS's file format description?

This section describes format used by XaoS for animations, confiugration
files and saved possitions. All these files have common format, designed
to be easily readable, to allow manual editing of files and converting them
into another program.

I also taken a care to make it easily extensible for future versions of XaoS
so I hope there will not be many incompatibilities between various XaoS's
versions.

File is simple set of commands executed seqentially. XaoS does not provide
any varibles/cycles as usual scrippting languages but possible future
extension to scheme should be easy since format uses scheme-like syntax.
Syntax of every command is:

@example
(command_name @var{<param1> <param2>...})
@end example

Where parameters are optional and separated by whitespace (arbitary number
of spaces, tabs and enters). Parameters should have following types:


@table @code
@item integer
number w/o decimal point (@code{123})
@item float
floating point number in decimal notation with optional exponent (@code{1.23E2})
@item keyword
text started by apostroph @code{'}. It is used to pass various string constants 
like formula name (@code{'mandel}) Apostroph is required for scheme compatibility
@item string
Text inside double quotes. The only parameter that should contain whitespaces
@item boolean
@code{#t} for true or @code{#f} for false
@end table

XaoS supports following functions: (functions with * invokes recaluclation)

@subsection Control functions:
XaoS command language lacks any control contstructions like loops, if etc,
since it is expected that scheme interpreter will be used in case such thinks
will be required.

@defun (load @var{string})
This function loads and interprets file. It works in similiar way as include
in C.
@end defun

@defun (initstate)
This function reset XaoS state to default values from version 3.0. This
command should be at the beggining of each animation file, since otherwise
some stuff previously enabled by user should make inexpected effects.
State is not reseted by default before playing animation since it should
make impossible to write macros. Current version IMO don't need them, but
in future versions, where scheme programming language will be available this
should be much more interesting subject.
@end defun

@subsection Timming functions:
  This functions control animation replay speed.

@defun (usleep @var{integer})

This function waits selected amount of time(in usec) until next commands
are processed. Screen is recalculated and displayed at the begining of
usleep when some (*) command were procesed in the last frame. Remaining
time is spent by waiting or performing animation you entered by animation
commands(see later)
@end defun

@defun (wait)

Waits until screen is animated (fractal is in calculation or some filters ---
like motionblur does some animation. Do not call this function when zoom,
or continuous rotation is active otherwise deadlock happends. It is
recomended to call it, before text subtitles are displayed, since it looks
ugly when they are displayed over blocky unfinished fractal. It may look
well for you but ugly for others. Also you should call it after animation is
performed and before switch to another fractal happeds, since switch to
fractal involves calculation, screen is stopped for a while and unfinished
fractal there looks ugly. You should also call it, when you want to do
something as soon as possible.
@end defun

@defun (textsleep)

This function is similiar to usleep, but should be used after text subtitle
is displayed. Time to sleep is calculated from number of letters displayed
and letters per second value. Letters per second value should be adjusted
by users, so this provides mechanizm for finetuning speed of subtitles.

@end defun

@subsection Fractal context functions:
Fractal context contain informations about current fractal such as formula,
coloring modes etc.

@defun (formula @var{keyword}) (*)

parameter keyword specifies formula you want to use. Following keywords
are supported:mand, mand4, mand5, mand6, octo, newton, phoenix and newton
The formula is switched and some other fractal context variables are
switched to selected formula's defaults:
julia/mandelbrot mode, current view.
Command works in same way as number key in ugly interface.
@end defun

@defun (julia boolean) (*)

Selects whether julia or mandelbrot version of fractal will be caluclated
@end defun

@defun (juliaseed @var{float float}) (* only when fast julia mode is off)

Selects julia seed (real and imaginary part)
@end defun

@defun (perturbation @var{float float}) (*)

Selects perturbation value for mandelbrot version of set
@end defun

@defun (plane @var{integer}) (*)

Selects plane number (same as in ugly interfact minus 1---starts with zero)
I choosed numbering of planes instead of names because I was unable
to find some nice, short and descriptive names for them.
@end defun

@defun (incoloring @var{integer}) (*)

Selects inside coloring mode. Number works in same way as in plane 
command
@end defun

@defun (outcoloring @var{integer}) (*)

Same as incoloring but for outside coloring modes
@end defun

@defun (intcoloring @var{integer}) (*)

Selects truecolor inside coloring mode. Number works in same way as in plane 
command. Has effect just wjem outcoloring mode is set to 10 (truecolor
coloring)
@end defun

@defun (outtcoloring @var{integer}) (*)

Same as intcoloring but for outside coloring modes
@end defun

@defun (maxiter @var{integer}) (*)

Sets maximal number of iterations
@end defun

@defun (range @var{integer})

Sets solid guessing range i.e how large rectangles will be filled by
solid color when all four coners has same color.
0 disables this feature (increases precisity and slowes down)
@end defun
@defun (periodicity @var{boolean})

Enables/disables periodicity checking
@end defun

@subsection Viewport functions:
Current viewport is part of fractal context, but I describe it here
separately to simplify orientation in this document. XaoS uses 4 numbers
to specify viewport---first two are real and imaginary coordinate of
center of view and next two are real and imaginary ranges. I decided
to use both ranges instead of ``rectangular'' view to allow specify viewport
more exactly to make animation nice even in unusual window dimensions.
Of course you should use both numbers equal. Viewport is before calculation
scalled according to current window dimension and smalles possible
viewport where image is correct(i.e not too wide/shrink) containing
whole selected viewport is displayed. So you should expect a bit more
stuff on the screen than you choosed. 

@defun (angle @var{float}) (* - Just when fastrotate mode is disabled)
Set rotation angle in degrees
@end defun

@defun (view @var{float float float float}) (*)

This function simply sets viewport.
@end defun

@defun (animateview @var{float float float float}) (*)

This function is very similiar to previous one, except that it is expected
that view will be changes just slightly so recaluclation with just
ANIMATE priority (see fastmode command) is performed.
@end defun

@defun (moveview @var{float float})

This is animation function. For whole time selected by usleep after
this frame will be spent by moving smoothly center of viewport
to selected one
@end defun

@defun (morphview @var{float float float float})

This function is similiar to previous one except it allows also 
zooming/unzooming
@end defun

@defun (fastrotate @var{boolean})
Enables/disables fast rotation mode. When fast rotation mode is on,
XaoS is slower, but changing of angle does not require recaluclation.
@end defun

@defun (morphangle @var{float})

This function smoothle morphes current angle to new one. Parameter
is in degrees. Requires fastrotation mode enabled
@end defun

@defun (autorotate @var{boolean})
Enables automatical continous rotation. Works just when fastrotate mode is
enabled.
@end defun

@defun (rotationspeed @var{float})
Adjust rotation speed. Parameter is in degrees per second.
@end defun



@defun (zoomcenter @var{float float})

This function sets center where you want to zoom/unzoom (where you pointed
mouse in ugly interface). Parameters are not screen coordinates but
coordinates in the fractal.
@end defun

@defun (zoom)

Starts zooing to point choosed by zoomcenter. This works in same way as
button1 in the ugly interface. I don't recommend using this in manualy
done scripts since it is not easy to expect result and result should
differ slightly at different platforms/framerates. After zooming stops
it is recommended use animateview to fix this possible error.
In manually writeln scripts I expect
Zooming is performed until stop command is executed.
@end defun

@defun (unzoom)

Like zoom but starts unzooming
@end defun

@defun (stop)

Stops zooming/unzoming (not imediately but after short time required for
slowdown)
@end defun

@defun (maxstep @var{float})

Selects speed of zooming/unzooming. Step specifies how large
amount of range will be taken away each 1/20 of second.
(0 means nothing, 1 means everything - this value is incorrect)
Higher values means faster zooming
@end defun

@defun (speedup @var{float})

When zooming/unzoming every 1/20 of second the speedup value is added
to current step until maxstep is reeached. So this value selects
speedup/slowdown of animation. Both this functions are more for internal
use of XaoS then for manually wrote scripts.
@end defun

@subsection Fast julia mode functions:
Julia seed should be changed also using normal juliaseed function

@defun (fastjulia @var{boolean}) (* - just with #f)

Enables/disables fast julia mode.
@end defun

@defun (morphjulia @var{float float})

Morphes seed from current one into new one linerary.
@end defun

@subsection User interface functions:

@defun (fastmode @var{keyword})

Image should be recalculated in two modes - fast mode, when after
fixed amount of time caluclation is stopped and displayed with
possibly lowered resolution and then resolution is slowly improved.
Normal mode recaluclates image and displays it when finished. It also
stops timming, so time spent by calclatig of image should differ in
replay. (and next frames will not be replayed faster/slower to
``get in time'')

By default new images are caluclated using normal mode but animation
is caluclated using fast mode. You can change this behaviour by 
specifying:

@table @code
@item never
Fast mode will be disabled
@item animation
The default behaviour
@item new
Use fast mode even for new images
@end table
@end defun

@defun (filter @var{keyword boolean})

Enables/disables selected filter. Keyword select filter and shoud
be one of the following:
@table @code
@item blur
motion blur filter
@item stereogram
random dot stereogram
@item interlace
interlace filter
@item truecolor
Truecolor emulator (recommended to enable in case your images rely on
truecolor, smooth grades or palette size)
@item edge
wide edge detectio filter
@item edge2
Narrow edge detection filter
@end table
@end defun

@subsection Palette functions
XaoS has small problems with restoring of palette. I had two goals in
save/replay mechanizm - to replay animations as exactly as possible and
to replay animation in highest possible quality (even higher then when
they was recorded). This two goals can not be solved in following situation:
XaoS uses palette as large as possible(approx 250 in 8bpp, 65536 in truecolor
etc...). So when palette is saved in truecolor mode and replayed in 8bpp it
has to be shorter and when it is saved in 8bpp and replayed in 65536 it
is bigger. So do not rely on palette much. First 200 entries should be
OK but later ones should be different. Another problem is color cycling.
Since on slower computers image recaluclation takes longer time and
color cycling is asymchronous  process, replay can not be exact.
So after you stop cycling, palette should be shifted differently than when
recorded. Please DO NOT RELY ON ROTATED PALETTES.

Following functions are provided:

@defun (defaultpalette @var{integer}) (* --- do not recaluclate in most of 8bpp modes)

Sets the default palette. The parameter says how much is palette shifted
(by preious cycling). Should be 0 in the most cases.
@end defun

@defun (palette @var{integer integer integer})

Generates random palette. First number specifies algorithm. It should be
usefull for possible future improvements and must be 1 for now.
Next parameter is random seed for palette. And the last one specifies
shift like in (defaultpalette)
@end defun

@defun (cycling @var{boolean})

Enables/disables color cycling. Note that on devices, where color cycling
is impossible this command is ignored.
@end defun

@defun (cyclingspeed @var{integer}) 

Sets cycling speed(how many shifts per second). Numbers lower than
zero inverses direction of cycling
@end defun

@subsection Text output functions
To make possible writting of commented tutorials XaoS has simple text output
functions too.

@defun (text @var{string})
Displays text to the screen
@end defun
@defun (textpossition @var{horizontal} @var{vertical})
Lets you specify possition of displayed text. You may choose from 9
possitions. @var{Horizontal} parameter should be one of following keywords:
@code{'left}, @code{'center}, @code{'right} and @var{vertical}: @code{'top},
@code{'middle}, @code{'bottom}
@end defun

@defun (message @var{string})
Works in same way as @code{text} but uses string as index to message catalog,
so it should be used for translatable tutorials.
@end defun

@defun (letterspersec @var{integer})
Lets you adjust letters per second value used by textsleep. This is not
recomended to use from animation since it should be best to let user tune
it for himself. This function should be used in configuration file.
@end defun

@defun (clearscreen)
Clears screen...
@end defun

@defun (display)
Displays fractal again. After text is displayed (or screen cleared), screen
is not updated anymore to prevent overwriting of text. This is keept for
compatibility with future version, where movement under text subtitles should
be possible. You need to call @code{(display)} when you want to draw fractals
again. It should be also used to clear subtitles (it redisplays screen with
fractal)
@end defun


Example:

@example
;configure everything for the first frame
(palette 1 1163254293 0)	;custom palette
(filter 'stereogram #f)		;no filters
(filter 'interlace #f)
(filter 'blur #f)
(formula 'mandel)		;mandelbrot set
(fastmode 'animation)		;default fast mode
(fastjulia #f)			;normal mode
(cycling #t)			;enable cycling
(cyclingspeed 7)
(maxiter 276)			;higher number o fiterations
(outcoloring 0)			;no in/out coloring/plane
(incoloring 0)
(range 3)			;default range for solid guessing
(plane 0)
(usleep 1000000)		;second frame start here
(moveview -1.8101154154614007889 -8.2687205907162041209E-05)
				;just move the image
(usleep 1000000)		;thirt frame
(morphview -1.8101154154614007889 -8.2687205907162041209E-05
            6.277210971069452361E-10 6.2772109785334669875E-10)
				;10 seconds of zooming into selected rectanlge
(usleep 100000000)
@end example

@subsection XaoS galerry

I plan to make XaoS galerry of animations and possition files at XaoS homepage
so please send me all your nice animations and images you created using XaoS
to @code{hubicka@@paru.cas.cz}

@c %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@node Hacker, , User, Top
@chapter Hacker's guide

This charapter contains documentation for those who are interested in
improving, studying or using of XaoS sources in other programs. 
It includes documentation of those parts of XaoS I think they should be
usefull for someone.

@menu
* driver::		Driver API description
* xthreads::		XaoS thread library
* filters::		Filters
* algorithm::		Algorighm description
* timerlib::		The timer library
@end menu

@node driver, xthreads ,Hacker ,Hacker
@section Driver API description

To port sucessfully XaoS to some platform you need:

@itemize @bullet
@item
ANSI C compatible optimizing compiler. Note that optimizing compiler is really
required, since XaoS is coded to be good target for optimizations and don't
have any routines coded in assembly, so if you will use some bad compiler, you
should receive more than ten times slower result. Also note that some
compilers has serious problems with compiling XaoS --- like most of DOS compilers
(Watcom C, Borland C, Microsoft C etc...), plan9 compiler also has serious
problms with @code{formulas.c} . They generate incorrect code or
crash during compilation. I highly recomend to use GNU C compiler.
@item
Fast way to avoid division by zero/owerflow and other floating point
exception. XaoS is curefully coded to not to crash in this case, but don't
have any tests to avoid such situation and expect random result in such case.
Many plantforms provide way to switch coprocesor into mode, where 1/0 is
evaulated into Inf etc. I there is no such way, try to use some kind of signal
handler that will ignore such exceptions. This way should be slow, so if you
really must use it, please contact me and we shall discuss speed issues/add
some tests into most freqvent exceptions in XaoS. If your platform don't
provide any such way, contact me too and I will have to introduce plenty of
tests as ifdef, wich shlould greatly polute code and redce speed :(.
@item
Text or graphics output device. If you have only text output device, you may
use AA driver, wich renders fractals into high quality ASCII art. In this case
you might skip this section, download AA-lib (http://www.ta.jcu.cz/aa) and
read porting section of AAlib manual. Graphics device must one of:

@itemize @bullet
@item 8bits per pixel with user definable palette @code{C256}
@item 8bits per pixel with static palette @code{FIXEDCOLOR}
@item 8bits per pixel with static grayscale @code{GRAYSCALE}
@item 16bits per pixel with 5 bits per each color, Red first, Green last @code{REALCOLOR}
@item 16bits per pixel with 5 bits per green and blue, 6 for green, red first @code{HICOLOR}
@item 24bits per pixel with 8 bits per each color, Red first @code{TRUECOLOR24}
@item 24bits per pixel with 8 bits per each color, Red first @code{TRUECOLOR24}
@item 32bits per pixel with highest 8 bit unused, otherwise like previous @code{TRUECOLOR}
@item 32bits per pixel with highest 8 bit unused, otherwise like previous at little edian machine @code{TRUECOLORMI}
@item 1bits per pixe, zero is black, most significant bit first, lines are aligned @code{MBITMAP}
@item 1bits per pixe, zero is black, most significant bit last, lines are aligned @code{LBITMAP}
@item 1bits per pixe, zero is white, most significant bit first, lines are aligned @code{MIBITMAP}
@item 1bits per pixe, zero is white, most significant bit last, lines are aligned @code{LIBITMAP}
@end itemize

Please contact me if you have different kind of device. Some modes (like
missordered truecolor modes) should be added really easily if required.
Note that mono/16 colors devices will be probably never supported 
internally by XaoS, since I expect they will be slower than 8bpp, so XaoS
will internally work in 8bpp and then image should be converted. Contact me
if you want to write such convertor.
@item
Some way to save images. By default XaoS uses pnglib, wich is ported to many
platforms, but there is still many other. If your system has some standard
image format, wich is easier to handle than .png, contact me and I will show
you, how to add such support to XaoS.
@item
Stdio compatible library (this is problem at Mac or BeOS)
@end itemize

Ugly interface is designed to make writing of new drivers as easy as possible.
You need to write just few functions to fill following table:
(use file @code{ui_template} for starting of writing new driver from scrath)
@example
struct ui_driver @{
  char *name;
  int (*init)(void);            /*initializing function. returns 0 if fail*/
  void (*getsize)(int *,int *);	/*get current size..in full-screen versions
                                  i.e svga and dos asks user for it*/
  void (*processevents)(int,int *,int *,int *,int *);
                                /*processevents..calls ui_resize,ui_key
                                  also returns positions of mouse..
                                  waits for event if first parameter is
                                  1*/
  void (*getmouse)(int *,int *,int *);
                                /*returns current mouse positions*/
  void (*uninit)();             /*called before exit*/
  int (*set_color)(int,int,int,int);
                                /*alloc palette color and returns number*/
  int (*set_range)(ui_palette *palette,int start,int end)
                                /*Set palette range*/
  void (*print)(int,int,char *);/*prints text*/
  void (*display)();            /*displays bitmap*/
  int (*alloc_buffers)(char **buffer1,char **buffer2);/*makes buffers*/
  void (*free_buffers)(char *buffer1,char *buffer2);/*frees buffers*/
  void (*flip_buffers)(void);   /*prints text*/
  void (*clrscr)(void);         /*Clear screen*/
  void (*mousetype) (int type); /*Change mouse cursor*/
  void (*driveropt) (void);     /*Driver depended actions*/
  void (*flush) (void);         /*Flush current state to screen*/
  int textwidth;                /*width of text*/
  int textheight;		/*height of text*/
  char **help;                  /*help text*/
  int helpsize;                 /*size of help in lines*/
  struct params *params;        /*command line parameters*/
  int flags;
  float width,height;
  int maxwidth,maxheight;
  int imagetype;
  int palettestart,paletteend,maxentries;
@};
@end example

@subsection Functions

Ui uses following functions to communicate with driver:

@defun init
  function that initializes driver and returns 1 if success and 0 if fail
@end defun
@defun getsize (int *@var{width},int *@var{height})
  returns size of screen(window) x and y
@end defun
@defun processevents (int @var{wait}, int *@var{x},int *@var{y}, int *@var{buttonmask}, int &@var{keys})
  gets new keyboard/mouse events. parameters:
  @table @var
  @item wait 
     if 1 function can wait for next event otherwise just lookup if 
           something comed. This is usefull on multitasked os where xaos
	   does not eats unnecesaru cpi.
  @item *x,*y  
    here returns current positions of mouse
  @item *b 
     returns mask of @code{BUTTON1},@code{BUTTON2},@code{BUTTON3} for mouse buttons
  @item *k 
    returns mask for cursor keys 
    @table @code
    @code{1}
    left
    @code{2}
    right
    @code{4}
    up
    @code{8}
    down
    @end table
    @end table
    function also calls @code{ui_key}(ASCII character) and ui_resize if required

    note in case of problems freeing/allocating inside processevents you may 
    call @code{ui_call_resize} that calls resize later outside this function
@end defun

@defun uninit
 Unitialises driver --- called before exit.
@end defun

@defun set_range(ui_palette *@var{palette}, int @var{start}, int @var{end})
This is an preffered way to set palette (second way is @code{set_color})
when @code{imagetype} is @code{UI_C256} (256 color with palette) one of this
two functions is required. In truecolor modes they are unused. In case direct
access to palette is possible at your platform, define this one. Function is
expected to set all color cells between @var{start} to @var{end} to colors
defined in @var{palette}. @code{Ui_palette} is array of @var{ui_rgb}. @code{Palette[0]}
is color for entry number @var{start}. @code{Ui_rgb} is an array of @code{char}.
@code{Palette[0][0]} is red field of entry number @var{start}, @code{Palette[0][1]} is
green and @code{Palette[0][2]} is blue. @code{0} means black and @code{255}
means full intensity. Use @code{NULL} if your driver don't support this call.
@end defun

@defun set_color (int @var{r},int @var{g},int @var{b},int @var{init})
  This is an secondary way, that should be used at platforms w/o direct
  palette access (like X11 or static color schemes). It receives RGB value
  of color, and returns index of color cell with this color or -1 if no more
  color cells available. An @var{init} parameter is set to 1, when first entry
  of palette is allocated, @code{set_color} is expected to free all color
  entries previously allocated. Use @code{NULL} if your driver don't support
  this call
@end defun

@defun print (int @code{x},int @code{y}, char *@code{text})
  prints text to screen at possition x/y
@end defun

@defun display (void)
  displays current buffer to screen
@end defun

@defun alloc_buffers (char **@var{buffer1},char **@var{buffer2})
  allocs two buffers that can hold screen size bitmap. 
  Also sets current buffer to buffer1. Since version 2.1 returns scanline 
  size in bytes(usually width) and 0 if fail. This is usefull on systems, that
  allocated bitmap bigger than window/screen(dividable by 4 or so)
@end defun

@defun free_buffers(char *@var{buffer1},char *@var{buffer2})
  frees allocated buffers
@end defun

@defun flip_buffer (void)
  flips buffers --- set current buffer to other one
@end defun

@defun flush (void)
  This function should be used by drivers with buffered output to flush
  output buffers. Other driver should set it to NULL.
@end defun

@defun rotate_palette (int dirrection)

  function used for palette rotating. It is not required. Set to NULL if
  it is unimplemented in your driver. 

  When rotating is on this function is periodicaly called with direction 
  attribute. It must rotate all colors 1-number_of_allocated direction steps 
  forward except first one.   This should be implemented also using cmap array 
  in zoom_context that contains correct rgb values. 
  
  So you may use ui_getcontext to get zoom_context and then
  set context->numcolors colors in array cmap.
@end defun

@defun mousetype (int type)
   This function is used to change mouse cursor. It receives following values:
   @table @code
   @item NORMALMOUSE
     This mouse is usually displayed at screen, when UI waits for user
     commands
   @item WAITMOUSE
     This mouse is displayed when UI is busy(should be famous wait clocks)
     or you may use mouse defined in ui_dos --- mandelbrot set
   @item REPLAYMOUSE
     This mouse is displayed during replay. Should be none at fullscreen
     drivers, since blinking mouse cursor during replay looks ugly. At
     windowed system disabling mouse looks ugly, so it should be some funny
     cursor.
   @end table
   You should use NULL if your driver don't support this.
@end defun

@defun clrscr (void)
This function is
@end defun

@defun driveropt (void)
  This is an optional function (should be set to NULL) that should be used for
  various driver depended actions. You should use ui_menu call (see uinew.c
  for examples of usage) to make some driver depended menu.
@end defun
@subsection Other information
Also some additional variables are used to inform ui about driver.
All this values can be changed by init functions in case they are unknown
before.

@table @var
@item textheight,textwidth
  width and height of your font
@item palettestart,paletteend
  First and last palette entry, that should be changed. This you should use
  to avoid changing of entries reserved for window system, text, mouse etc.
@item maxentries;
  Number of allocatable entries. Normally should be
  @var{palettestart}-@var{paletteend}
@item imagetype
  defines type of image. Should be one of following values:
  @table @code
  @item UI_C256
    clasical 256 color with palette scheme used by most older graphics
    adapters. You should use it also for staticcolor schemes but they are
    not supported well in current version.
  @item UI_TRUECOLOR
    32bpp truecolor mode
  @item UI_TRUECOLOR24
    24bpp truecolor mode. 
  @item UI_HICOLOR
    16bpp hicolor mode (65536 colors)
  @item UI_REALCOLOR
    16bpp realcolor mode (32768 colors)
  @end table
@end table



FOLLOWING PART IS NOT REQUIRED TO MAKE FIRST VERSION OF DRIVER WORKING.
so you may skip to REGISTERING DRIVER for first read and return here later.


@table @var
@item help
  help text. This text is displayed at the end of ui' help. So you can put
  your copyright there and additional informations about driver.


@item helpsize
  number of lines of help


@item params
  Using this you may define command line options for you driver.

  They are defined using params structure like:
  @example
  static struct params params[]=@{
    @{"-mode",P_NUMBER,&defmode,
      "Select graphics mode(same number as in interactive menu)"@},
    @{NULL,0,NULL,NULL@}  /*this is MUST be last option field*/
  @};
  @end example

  every line is one parameters. List ends with @code{@{NULL,0,NULL,NULL@}}.
  First filed is option name.
  Second field is type of parameter:
  @table @code
    @item P_SWITCH 
    no parameter - variable is just set to 1 if option
    @item P_NUMBER 
    integer number
    @item P_STRING 
    string
    @item P_FLOAT 
    floating point number (variable is float)
  @end table
  Third is pointer to variable that is changed if option is set. 
  It is for example @code{int*} for @code{P_NUMBER} or @code{P_SWITCH} and so on..
  Last one is help text. Displayed by @code{ui -h}


@item width,height
  see FLAGS. May be set to @code{0.0, 0.0} for the begining

@item maxwidth,maxheight
  see FLAGS. May be set to 0,0 for the begining

@item FLAGS
  This variable says more about your driver. You may start with value 0.
  But for final version it is recomeded to read following section curefully.

  Flags are uppercase constants and should be set by following way:

  @code{ASYNC_PALETTE | PALETTE_ROTATION}

  following switches are supported:

  @table @code
  @item RANDOM_PALETTE_SIZE
    random size of palette. This is used in X where palette is shared between
    programs. By default xaos allocates all available colors up to 256. This
    is not very nice to other aplications in X. So randomsize causes that
    just some random number of colors(between 8-256) are allocated. 
  
    Also when this variable is off XaoS expects that allways same number of
    colors is available.
  @item UPDATE_AFTER_RESIZE
    recalculate and redraw screen even if its size is not changed.
    In case that resize precodure destruys data in buffers
  @end table
  Palette rotation options:

    Palette rotation should be implemented by various ways.
    You may define following values to let xaos know about features/limitations
    of your implementetion:

    @table @code
    @item ROTATE_INSIDE_CALCULATION
     call rotate routing inside calculation loop too?  
     (vbuff should include incorrect data)
    @item PALETTE_REDISPLAYS
     If you rotate_palette function displays buffers(like in
     truecolor modes. Set this to 1 and ui will handle this more
     effectivly)
    @end table

  Screen/window size informations

    Xaos needs to know exact size of displayed images. This is required
    for random dot stereograms and also for keeping fractals in their shape
    (do not make them wide on 640x200 resolution etc.)
    So minimally one of the following values should be defined.
    (they are sorted in order I preffer them)
  @table @code
    @item SCREENSIZE
     values width/height specifies exact size of screen/window in centimeters
    @item PIXELSIZE
     values width/height specifies exact size of one pixel in centimeters
     This is better for windowed enviroments where window size is often changed
    @item FULLSCREEN
     driver runs fullscreen. XaoS automatically uses default screen size
     (29.0cm x 21.5cm)
    @item RESOLUTION
     driver does not know exact screen size. But knows resolution used.
     (it is in variables width/height) XaoS automatically calculates
     pixel width using:29.0cm/maxwidth
     and height: 21.5/maxheight
   @end table
   Of course default width and height can be changed by command line options.
   You may also use combinations like:
   
   @table @code
   @item SCREENSIZE | FULLSCREEN 
   the best for fullscreen drivers
   @item PIXELSIZE | RESOLUTION 
   the best for windowed drivers
   @item FULLSCREEN 
   for fullscreen drivers than have no idea about screen size...  
   @end table

   do not forget to set @var{width}, @var{height}, @var{maxwidth}, @var{maxheight} fields if required.
@end table


@subsection Registering driver

Than just register driver to @code{driver.c} and you may compile :)
You may use @code{ui_template.c} as driver template..

You may also look at xthreads library description if you are
porting XaoS to some SMP platofrm.

Please let me know if you want to start code some driver.

@node xthreads, filters ,driver ,Hacker
@section XaoS thread library

This description should be usefull for those, who want to port XaoS
into multiprocessor platforms and those, who want to implement some
filter or other relativly computational expensive code. Note that thread
library should be mapped into nothread calls, in case host does not allows
multithreading or it is not SMP architecture (since this library is
used only to distribute calcualtion into other CPUs)

XaoS thread library is simple map of few functions required by XaoS
to system library for threads.

It has following variables:

@deffn Variable ethreads
This is set to 1 in case that threads are enabled
@end deffn

@deffn Variable nthreads
Number of threads
@end deffn

It and following calls:

@deftypefn Function {void} xth_init (int @var{threads})
This function initializes threading library (starts threads, sets
@var{ethread} to 1 and @var{nthreads} to n. @var{Threads} parameter should be
set to 0 --- autodetection or number of threads users wants. In case threads
is set to 1, threading library is disabled and following functions are
mapped into ther nothread_ equivalents defined in @code{xthread.h}.

Note that threads are not identical --- there is main thread (one that called
xth_init) that comunicates with drivers, controls calcualtion etc. and other
tasks that are waiting to orders from main task. They also can't use functions
from xthread library.
@end deftypefn

@deftypefn Function {void} xth_uninit (void)
This function uninitializes thread library --- kills child threads, sets
@var{ethread} to 0 and @var{nthreads} to 1. 
@end deftypefn

@deftypefn Function {void} xth_function (xfunction *@var{function}, void *data, int @var{range})
This function is used in case, engine wants to perform some operation at image
in parael. It is expected to wait until all threads are ready and start @var{function} 
at all threads including control one with following paramters: @var{data} --- this
parameter is same as
@var{data} passed to xth_function, @var{taskinfo} --- pointer to structure
taskinfo, that is platform depended (defined in @code{xthread.h}) but must
have at least field @code{n}, that holds number of thread (control thread has
0 and other numbers in range 1 -- @var{nthreads}). Next two parameters is
range of image, function is expected to do action. Xth_function is expected to
divided @var{range} into @var{nthreads} equal pieces and pass always start of
piece and start of next piece (@var{range} in case of last one). Function does
not wait for other threads at the end and returns imediately to main thread
after @var{function} returns.

This function is called approx 5--10 times per frame
@end deftypefn

@deftypefn Function {void} xth_sync (void)
This functions waits until all threads are ready for next order from main
task. 

This function is called approx 5--10 times per frame
@end deftypefn

@deftypefn Function {void} xth_bgjob (xfunction *@var{function}, void *@var{data})
This function is expected to behave as follows: look if there is any thread
waiting for orders, if so, ask him to call @var{function} with similiar
conventions as in xth_function except that range parameters are set to 0.
Otherwise it starts function in normally (at foreground).

This function is called once per frame.
@end deftypefn

@deftypefn Function {void} xth_nthread (struct taskinfo *@var{s})
This function should be used to determine number of current thread. Do not use
@code{taskinfo->n} instead since in case threads are disabled, it should be
defined to 0 and that allows optimizer to perform better optimizations.
This function should be called by all threads.
@end deftypefn

@deftypefn Function {void} xth_lock (int @var{n})
@end deftypefn
@deftypefn Function {void} xth_unlock (int @var{n})
Lock/unlock lock number @var{n}. At least @code{MAXSEMAPHORS} locks must be
available.

Note that locks are used always for very short fragments of code so they
needs to be fast. So spinlocks are maybe better than Dijskra semaphors.
Untested. They are called once per calculated line/row during zoom and
once per approx 10 pixels during calculation of new image.
@end deftypefn

@deftypefn Function {void} xth_sleep (int @var{n}, int @var{l})
It is expected to atomically unlock lock @var{l} and sleep in queue @var{n}.
At least @code{MAXCONDS} queues must be available.
After it is waked up, lock @var{l} again. This mechanizm is used by
calcualtion of new image algorithm, but it is designed to minimize its calls,
so I expect they should be called once or twice.
@end deftypefn

@deftypefn Function {void} xth_wakeup (int @var{n})
Wake up some thread from queue @var{n}. Lock used by
sleep calls is locked in this cases. Function should also wake up all threads
if such operation is not supported by host API. With luck, this function
should not be called at all. It should be called by new image caluclation
routines in case queue is empty. This happends in case of 50 threads but
happeds rarely at two or eight threads according to my tests.
@end deftypefn

@deftypefn Function {void} xth_wakeall (int @var{n})
Similiar to wakeup but wake up all threads.
@end deftypefn


@node filters, algorithm ,xthreads ,Hacker
@section Filters

This is a brief description of filter system used internally by XaoS.
Filters in XaoS provides an object oriented interface to every part
of XaoS engine. Main filters are: User interface implemented in ui_helper.c
and zooming engine implemented in zoom.c. Filters are connected into
an queue - at the beggining there is just two filters here(zoom and ui)
but later additional filters should be inserted into the middle of queue
like an stereogram generation etc. The queue supports operations like
remove filter, add filter and initialize.

In the caluclation every filter should use data caluclated by filter lower
in the queue. Data are stored into image. So for example stereogram filter
should use fractal generated by zooming engine and create an stereogram.

This makes XaoS's code more flexible and makes easy future enhancements
like different zooming engine, image rotation, other special effects,
plug-ins and some other funny stuff since interface of each such part
is well defined and each filter has quite good control over his childs.
So stereogram filter should change palette, force zooming engine to change
depth, width and height of calchlated image to fit his needs and so on.

This document describes mainly creating of filter like stereogram generator
i.e. filter placed into middle of queue since I don't expect there will be
many people creating ``terminal'' filters (zooming engines/user interface
layer) note that different user interface is possible since user interface
layer is not the real user interface just set of high level functions that
should be called by main application like set_view. So in case you want
to use XaoS as an calculation engine in your program this document is probably
not for you.

Each filter is defined by filter_action structures as follows:
@example
struct filteraction @{
  char *name;
  char *shortname;
  int flags;
  struct filter *(*getinstance)(struct filteraction *a);
  void (*destroyinstance)(struct filter *f);
  int (*doit)(struct filter *f,int flags,int time);
  int (*requirement)(struct filter *f,struct requirements *r);
  int (*initialize)(struct filter *f,struct initdata *i);
  void (*convertup)(struct filter *f,int *x,int *y);
  void (*convertdown)(struct filter *f,int *x,int *y);
  void (*removefilter)(struct filter *f);
@};
@end example
This structure describes static filter's parameters (like its name) and
basic set of methods required for communication with resto of XaoS.
The name field describes filter's name like ``An random dot stereogram
generator''. Name is displayed by ugly interface in filter's menu. So
it is expected to be descrptive and shorter than 30 characters. The short
name is one word long name for filter like ``stereogram''. This name is
used by save files, possibly by command line parameters. Simply everywhere
where user should need to write it and writing long descriptive name should
be just wasting of time and disk space.

Flags field is kept for future enhancements and is expected to be 0 for now.

@subsection Creating / destroing of instance

Functions getinstance and destroyinstance are equvivalents to constructor and desctructor
in OOP. Getinstance is expected to create and fill following structure:

@example
struct filter @{
  struct filter *next,*previous;
  struct queue *queue;
  struct filteraction *action;
  struct image *image,*childimage;
  struct requirements req;
  struct fractal_context *fractalc;
  void *data;
  char *name;
  int flags;
  void (*wait_function) (struct filter *f);
  /*stuff for wait_function*/
  int pos,max,incalculation,readyforinterrupt,interrupt;
  char *pass;
@};
@end example
Altrought this structure seems to be long and complex, most of fileds are
unused at this time and rest of them are filled automatically by function:

@deftypefn Function {struct filter} *createfilter (struct filteraction *@var{fa});

That should be used to create instance. Only possibly interesting field
is data. It's pointer reserved for filter's internal use. So it should
be pointer to filter's internal variables if required. Following is
example implementation of getinstance with allocating of such additional
structure. In case nothing similiar is required you should use dirrectly
createfilter at getinstance's place.
@end deftypefn

@example
static struct filter *getinstance(struct filteraction *a)
@{
      struct filter *f = createfilter(a);    /*create filter structure*/
      struct stereogramdata *i=calloc(sizeof(*i),1);
                                             /*allocate internal variables*/
      /*initialize your variables here*/
      f->data=i;                             /*add pointer to internal data*/
      return (f);
@}
@end example

The destroyinstance is expected to free memory used by filter structure and
all internal data of filter. To free filter structure use normal free(filter);
So implementation of suchfunction should look like:
@example
static void destroyinstance(struct filter *f)
@{
     destroyinheredimage(f);
     free(f->data);
     free(f);
@}
@end example
The meaning of destroyinheredimage will be described later.


@subsection Initialization

During initialization phaste each filter says to his parrent what kind
of images it supports (this should depend on images supported by his child),
parent chooses best supported image format for his purposes and gives 
it to the child. Initialization is done in two pases.

First pass start by lowest filter in the queue and each filter passes to
his parrents requirement structure.

Second pass starts by the highest filter and each filter passes to child
an image and some other stuff. Then caluclation should begin.

Queue needs to be reinicialized after creating, resizing, adding/removing
of filter and similiar operations.

First pass is implemented using require function. This function is expected
to take care at child's requirements it received as parameter, fill
requirements structure and call require function of his parent filter.
@example
struct requirements @{
  int nimages;
  int supportedmask;
  int flags;
@};
@end example
The nimages field should be set to 1 or 2. In case it is 2, parent filter
must pass image with two buffers. Note that in case it is 1, parent should
pass image with two buffers too.

Supported mask is mask of supported image types by filter. Image types
are following:
@table @code
@item C256
  An normal 8bpp image with palette
@item REALCOLOR
  An 16bpp image with 5 bits for red, 5 bits for green and 5 bits for blue
@item HICOLOR
  An 16bpp image but with 6 bits for green
@item TRUECOLOR24
  An 24bpp truecolor image with 8bits for each color.
@item TRUECOLOR
  An 32bpp truecolor image with 8bits for each color.
@item LARGEITER
  An 16bpp image but w/o colors. It is expected to hold number of iterations
  it should be also tought as 16bpp grayscale image
@item SMALLITER
  Similiar to @code{LARGEITER} but 8bpp
@end table

In case you don't wory about palettes, allocations of colors and you do just
some operation with bitmap, so you wory just abour depth of image you should
use mask of following: @code{MASK1BPP} for 8 bit images, @code{MASK2BPP} for 16bit and so on.

The latest field of requirements structure is flags. It mask from following
constants:

@table @code
@item IMAGEDATA
  in case your filter requires data from previous frame untouched. In case
  this is not set, filters should reuse your image and change it. But some
  filters like and motion blur or zooming engine requires data from previous
  frame to construct new, so this flag should be set
@end table
there is no more flags supported at the moment. Function require should also
save child's require structure into filter->req for later use by initialize
pass. So you should look like:
@example
static int requirement(struct filter *f,struct requirements *r)
@{
  f->req=*r;    /*Save an child's requirements*/
  r->nimages=1; /*Just one image is required*/
  r->flags&=~IMAGEDATA;/*unset the imagedata field*/
  r->supportedmask=C256|TRUECOLOR|HICOLOR|REALCOLOR;
                /*mask of all supported image types*/
  return (f->next->action->requirement(f->next, r));
                /*call parent*/
@}
@end example
Next pass is main initialization. It goes in oposite order(from parent
to child) and child's inhers some stuff from parent like images etc...
The initialize structure receives an initdata structure:
@example
struct initdata @{
  void (*wait_function) (struct filter *f);
  struct image *image;
  struct fractal_context *fractalc;
  int flags;
@};
@end example
an wait_function is function called by filter during calculation that
lets the parent filters(usually user interface layer) to inform user
how calculation continues. Image is an image expected to be filled
by image in calculation phaste. Fractalc is pointer to structure that
will contain information about fractal during calculation(like formula
type etc...) Flags is mask of following constants:
@table @code
@item DATALOST
 this is set in case, that data in image was lost(image was cleared or
 resized or freshly allocated). Filters that uses data from previous frames
 should take care to this flag. Zooming engine for example recalculates
 whole image since pixels from previous frame was lost.
 Note that data should be lost also in case, filter receives different
 image that in previous initialization since some filter behind was
 removed.
@end table
An inhering process is done using function:

@deftypefn Function void inhermisc (struct filter *@var{f},struct initdata *@var{i});

This function sets fields in filter structure like as fractalc or wait_func.
Inhering of image is quite complex, since new image needs to be prepared
for child. In order to save memory it is highly recomended to use same
image or at least same memory for data when passing to child. But this
is not allways possible. Following function implements heruistic to do this:
@end deftypefn
@deftypefn Function int inherimage (struct filter *@var{f},struct initdata *@var{data}, int @var{flags}, int @var{width}, int @var{height}, struct palette *@var{palette}, float @var{pixelwidth}, float @var{pixelheight}) 
You should call this function in yout initialize pass. It fills image and
childimage in filter structure, prepares initdata for child and creates
image for child. Note that it should fail in some cases and return 0. In
this case filter is expected to interrupt initialization and return 0 too.

An @var{flags} parameter is mask of following constants:
@table @code
@item IMAGEDATA
  in case your filter requires data from previous frame
@item TOUCHDATA
  In case your filter touches data in output image. This is very usual but
  there is some filtrs (like interlace or subwindow that don't)
@item NEWIMAGE
  Set in case your filter can not deal with shared images (images that have
  input data in same memory are as output)
@end table
@var{Width} and @var{height} should be set to 0 in case you want same width/height as
in parent image or width and height of image you want to pass to child.
@var{Palette} is palette of image you want to pass. Set to @code{NULL} if palette should
be inhered from parent's image (usual).
@var{Pixelwidth} and @var{pixelheight} specifies physical size of pixel in centimeters.
If set to 0 they are inhered from parent's image.
@end deftypefn

In case you use inherimage mechanizm you also must call destroyinheredimage
in destroyinstance function and updateinheredimage at the begining of calculate
function.

Example implementation:
@example
static int initialize(struct filter *f,struct initdata *i)
@{struct stereogramdata *s=f->data;
  inhermisc(f,i);
  if(!inherimage(f,i,TOUCHIMAGE,0,0,NULL,0,0) return 0;
  /*initialize here*/
  return(f->previous->action->initialize(f->previous,i));
@}
@end example
Also note that fractal context hold pointer to fractal palette. In case
You don't change image palette everything is OK. But in case child's image
differs from parents image, there should be two behaviours --- fractal's palette
is child one (this should be common for example in conversion filters (
8bpp to truecolor etc)) or fractal's palette is parent's one (like in
edge detection filter). By default fractal's palette is kept to parent's one.
This should be changed by setfractalpalette call. It has two parameters ---
filter structure and palette. When you pass as palette child's palette,
fractal's palette will be changed to child. In case you pass NULL. Changing
of palette will be disabled (like in motion blur filter in 8bpp mode).
Note that this is changed just in case you still have access to fractal palette.
Some parent should redirect palette before. Than this functio does nothing.


@subsection Caluclation

Main caluclation is done using doit function. It is expected to call
child's caluclation function when required and apply filter at output.
It receives flags. Only flag in @code{INTERRUPTIBLE} for now. It is mainly
for zooing engine so I do not describe it here. But filter is expected to
pass this flag to child. Next parameter is time in milliseconds that
expired since last doit call. It should be used to caluclate speed
of animation.

Calculation loops returns flags. Flags is mask from following constants:
@table @code
@item ANIMATION
 in case filter performs some animation and expect that calculation will be
 called again soon
@item CHANGED
 in case something changed in output image (usual)
@item INEXACT
 This is enabled by zooming engine in @code{INTERRUPTIBLE} mode in case that time
 exceeded.
@end table

An doit function changes image. Image structure contains following fields
significant for you:
@table @code
@item bytesperpixel
  number of bytes per pixel (image depth)
@item palette
  palette of image.
@item currlines
  array of pointers to beginings of every scanline of image
@item oldlines
  array of pointers like currlines but for previous image in case
  doublebuffering is enabled
@item nimages
  set to 2 in case doublebuffering is active
@item flipimage
  pointer to function that flips oldlines and currlines.
@end table

palette structure contains following significant fields:

@table @code
@item type
 type of palette/image (@code{C256}, @code{TRUECOLOR} etc...)
@item size
 number of allocated entries
@item pixels
 array of allocated entries. Conversion table from number of iteration
 to pixel value.
@item rgb
 Rgb values for pixels (@code{NULL} for @code{TRUECOLOR}, @code{HICOLOR} and similiar types)
@end table

To make easier writting calculation loops for different depths @code{pixel8_t},
@code{pixel16_t} and @code{pixel32_t} are predefined. You also can use include system
as in edge detection filter, that lets you write calculation loops just
once and use cpixel_t and it will be compiled for every bitmap depth.
See edge detection filter (engine/edge.c and engine/edged.c) for
implementation details.


@subsection Conversion

Convertup and convertdown functions are used for converting screen coordinates
to possition in fractal and back. Convertup is function that receives
coordinates in chield's image and is expected to convert them into coordinates
in parents image and call parent's convertup function.

Convertdown is reversed(from parent to child).

In case coordinates respond 1:1 you should use convertupgeneric and
convertdowngeneric. In other case implementation should look like:

@example
static void convertup(struct filter *f,int *x,int *y)
@{
    *y*=2;
    *x*=2;
    if(f->next!=NULL) f->next->action->convertup(f->next,x,y);
@}
static void convertdown(struct filter *f,int *x,int *y)
@{
    *y/=2;
    *x/=2;
    if(f->previous!=NULL) f->previous->action->convertdown(f->previous,x,y);
@}
@end example

@subsection Removing of filter

Before filter is removed from queue, removefilter function is called.
It is expected to clean up thinks filter changed. Should be NULL
in most cases.

@subsection Registering of filter

Once filteraction structure is filled, filter is done and you should try
to enable it. To enable it in user interface you need to edit ui/ui_helper.c,
add filter into uih_filters structure and increase uih_nfilters.
Note that order of filters in uih_filter is significant, since same order
is kept in filter queue, so you should specify if you want to be called
before/after filter xy.

Then it is high time to start experimenting.

Good luck!
@node algorithm, timerlib, filters ,Hacker
@section Algorithm description
The main idea behind XaoS is that it is not required to calculate the
whole image every frame. Most pixels are already calculated in the
previous frames. You usually don't have exactly the pixels you want,
but all within a range lower than a step between pixels are
acceptable. That is why the image flickers a bit and why points do not
blink randomly as in precalculated animations.
   
   This document describes some of the most important algorithms in XaoS
   @itemize @bullet
     @item Saving Previous Pixels
     @item Approximation Algorithm
     @item Moving Pixels to New Positions
     @item Calculating New Pixels
     @item Symmetry
     @item Calculation of Mandelbrot Set
     @item Dynamic Resolution
     @item Autopilot
    @end itemize   
   
@subsection Saving Previous Pixels

Ideally, all precalculated points should be saved and used for
building successive frames. I could not figure out a practical way to
implement this. To save all frames for half an hour would require 24
Mb of memory, and searching the saved frames would be more
computationally expensive than recalculating an entirely new frame.

One way was later used by program Frang. It remembers all pixels as
x,y and value fields and when it builds new image, it draws all pixels
to it and then browses image and fills it by new pixels. Possibly some
rle cache should be used for calculated pixels. Frang actually uses algorithm,
that takes away pixels out of screen, so it behaves exactly in same way
as algorihm described here. At the other hand, this method seems to require
much more memory than XaoS algorithm and drawing pixels/browsing image cost
quite a lot, so algorithm descibed here seems to be faster. Since it never
requires examining of whole image and new image is constructed using
block move operations.

For this reason only the last generated frame is used as reference.
This way the memory requirements are proportional to xsize * ysize. It
can be shown that this method is only about 2-5% slower during
zooming. Of course unzooming back to once browsed areas is much slower.
   
Because only the previous frame is used, another optimization can be
performed: Imaginary and real parts of the calculated image are not
precise since they are the result of successive iterations of same
algorithm. In order to prevent errors from being distributed to the
following frames their exact coordinates need to be known.
Fortunately, it isn't neccassary to save their values since it is
known that all real components in a row and all imaginary components
in a column are equal. Thus, the only things that must be saved are
the real components for every row and the imaginary components for
every column.
   
This allows for a substantial speed-up in approximation because the
calculation requires less data. Of course, some rows and columns fall
out of the threshold and new ones need to be calculate to fill in the
gaps in the frame.
   
Obviously, much less work is done. There are only @math{xsize + ysize}
calculations instead of @math{xsize * ysize}. So the main loop in XaoS looks
like this:
   @itemize @bullet
     @item Make approximations for rows
     @item Make approximations for columns
     @item Move old pixels to their new positions
     @item Calculate pixels for which there is no good approximation for
       their row
     @item Calculate pixels for which ther is not good approcimation for
       their column but there is one for their row
    @end itemize
       
   
@subsection Approximation Algorithm

  @unnumberedsubsec Introduction to problem
   
You can see that the approximation algorithm is central to the
implementation of XaoS. If the guess is incorrect the image will look
strange, boundaries will not be smooth and the zoom will flicker. On
the other hand, if it adds more new rows or columns than required,
zooming will become much slower. Also, in the instance of doubling
(i.e., using an old row or column more than once) the resolution will
lower. It is important to keep the increasing imaginary and real
components in the correct order. If a row and column of complex
coordinates follows one with higher coordinate values an improved
approximation can be attained by swapping their values.
   
The algorithm needs to be relatively fast. It is only used for @math{xsize + ysize}
values but if its speed is proportional to @math{O(n^2)}, it can be
slower than a whole recalculation of the image. Speeds of @math{O(n)} or @math{O(n * log(n))} are acceptable.
   
  @unnumberedsubsec Some simple algorithms to solve it
  
   
   
Initially, a very simple algorithm was used:
   
  Find the old row/column nearest the row/column that needs to be
  regenerated. If the difference between them is less than one step
  (@math{step = (end - beginning) / resolution}) then use it. Otherwise,
  recalculate a new one.
     
Finding the nearest row/column pair is very simple since it is always
greater or equal to the pair needing to be generated.
   
Surprisingly, this simple algorithm has almost all the problems
described above. Doubling was fixed by lowering the limit to @math{step / 2.}
This cause a considerable slowdown so the limit was returned to step.
Instead, the algorithm was changed to search for only row/column pairs
that are greater than the previous frame's row/column pairs. This is
the algorithm that was used in version 1.0
   
This algorithm still added to many new rows and columns and did not
generate smooth boundaries. For version 1.1 a heuristic was added that
preferred approximating rows/columns with lower values. This way it
did not occupy possible rows/columns for the next approximation. The
result was a speedup by a magnitude of four. In versions 1.1 to 2.0
many improvements were made to the heuristic to give it added
performance. The following example tries to explain how complicated
the problem is (O is the old coordinates and X is the values to be
approximated):
@example
        X1        X2        X3        X4        X5        X6        X7
O1 O2                    O3 O4 O5                   O6 O7 O8
@end example

The normal algorithm will aproximate X1 by O2, X3 by O4 but nothing
more. For the algorithm with threshold step instead of @math{step / 2}:

@example
  O2 to X1
  O3 to X2
  O4 to X3
  O5 to X4
  O6 to X5
  O8 to X6
@end example

But this will fail with X7. The second algorithm which relies on lower
values will do the following:

@example
  O1 to X1
  O3 to X2
  O4 to X3
  O5 to X4
  O6 to X5
  O7 to X6
  O8 to X7
@end example

O1 to X1 is wrong. And there is many and many other situations that
may occur. But you may see that the normal algorithm will calculate 4
new rows/columns but the heuristic saves all of these calculations.
   
  @unnumberedsubsec Current algorithms used
  
   
   
In version 2.1 work on this heuristic was disabled after I discovered
a suprisingly simple algorithm that solves all these problems. First I
decided to define exactly what is best aproximation. This should be
done by defining a price for every aproximation and choose the
aproximation with the lowest price. Prices are defined as such:
   
  Aproximating row/column x by y costs @math{dist(x, y) ^ 2}.
     
This prefers two smaller approximation errors before a single larger
error and describes my goal quite well.
   
The cost for adding a new row/column specifies when it is better to do
a bad approximation and when to add a new row/column. I use @math{(4 * step)
* (4 * step)}. This means that the approximation is acceptable when
@math{dist(x, y) < 4 * step}. Otherwise, adding a new row/column costs less.
Now the best approximation is known. All that is required is a fast
algorithm to do this. Surprisingly, this is possible in linear time
using a relatively simple dynamic algorithm. It uses approximations of
@math{length < n} to make a guess at the length of @math{n}. It can start by
approximating one row/column and then again for two, three up to
xsize/ysize rows/columns.
   
The algorithm starts by calculating prices for all possible new
positions for old row/column 1. Because of the pricing there are
maximally 8 new positions. (Other ones must cost more than adding new
row/column). Of course it is possible that there are no new positions.


For calculating the price of aproximations for row/column 2 I may use
previous one: Try new position n. Calculate the price and add the best
aproximation for the previous (row/column 1) one that uses a new
position lower than n(prohibits doubling or swapping). This shoud be
one of 8 positions or eventually adding of new one and not using
row/column 1 at all.

The same method can be used for the rest of the rows/columns. At the
end the best price may be found for the last row/column and return by
the way it was calculated. (For this I need the saved ``calculated
using'' values.) At this step the best approximation has been
determined.

To fill the table, @math{9 * n} steps are required and n steps to backtrack
best aproximation. The only problem is that this algorithm is still a
little slow (chiefly because of slow memory access on Intel
architectures). -But with some optimizing it works well.

This algorithm is almost perfect except that it occaisonally adds new
rows/columns to the wrong locations. It does not prefer to add new
rows/columns into holes. But it does not seem that this is the real
problem. The last optimization made was based upon the face that added
rows/columns do not have the exact real and imaginary components
calculated by (@math{beginning + x * step}) but lies at the average of left
and right neighbours. This makes the boundaries smooth and distributes
coordinates better. It also has the added benefit of making the input
better for future approximations.

Another danger during implementation if this algorithm is that adding new
rows/columns into their idead possitions should cause missordered results,
since some rows/columns should be off more that is distance between them.
To avoid this, I use algorithm that always examine start and end of block
of new rows/columns and linearly interpolates value between them. Special
care needs to be at the blocks that start at the begining or overs at
the end.

Implementation should be much faster using custom fixedpoint routines ---
first recalculate values that 0 means start of image and 65536 means end.
Than calculation is much cleaner. Values <0 and >65536 are of screen, 
calculation is independent at scale and many thinks should be
precalculated --- like tables for calculating price from distance.
Also dividing main loops into many specialized parts and avoiding
filing unnecesay parts of table helps. So current algorithm in XaoS is about 
5 or 6 times faster than first naive implementation.
   
@subsection Moving Pixels to New Positions

   
   
Since XaoS is using the approximation algorithm the following table is
filled for every row/column:
   @itemize @bullet
     @item calculate
     @item oldpoint
     @item position
   @end itemize
       
calculate is 1 if the current row/column is new and needs to be
calculated or 0 if no old pixels need to be moved. oldpoint is a
pointer to the old row/column that corresponds to the new one. This
pixel needs to be copied to the new location. position is the real and
imaginary components of the coordinates used for future
approximations. Because almost all points will be moved, the solution
seems to be simple: for every new point look at the row and column
table; copy it if required.

There is the problem that this minimally needs three memory reads for
every pixel (read calculate, oldpoint and index of old point). This is
too slow, so a small optimization is performed. Instead rewriting the
piece of code in assembly, normal memcpy is used to move blocks of
pixels to their new locations. This minimizes the internal loop and
access can be done more quickly since memcpy is usually optimized for
each architecture.

Using the row table, a list of blocks to move for every row is
created. With this new table all the pixels can be moved quickly. This
increased the speed of XaoS about four times and made this function so
fast that it is no longer a problem. (In fact, it takes much less
processing than all other parts of XaoS.)

@subsection Calculating New Pixels
   
The above optimizations make XaoS very fast, but another 30% increase
in speed is aquired by using a clever method for calculating the new
pixels. Many methods are known for saving calculations during the
generation of fractal images. The most powerful is boundary detection.
It relies on the fact that the Mandelbrot Set is connected with lakes.
You need only one pixel at the boundary, then traverse the whole set
and then fill the solid area inside. This method saves many
calculations but is too complex for adding just one line. Many claim
that it does not introduce any errors, but this is not true. It is
possible for a connected part of the lake to be so small that it is
not visible in smaller resolutions. In this case, boundary detection
misses the whole area. This algorithm is acutually used just for
calculating of new images (i.e. at the startup). 

XaoS uses modification of method known as solid guessing. The pixels
at the boundaries of a rectangle are calculated. If they are all the
same you may assume that this rectangle does not does not contain
anything and fill it.

This algorithm is further modified to operate on added lines. For this
it is at least as good as boundary detection and produces more
tangible errors. When adding a single line, the upper and lower line
may be examined for the nearest three pixels. If they are all the same
then it is assumed that 9x9 pixels are the same. This disables all
calculations inside solid areas and calculates as many points as
boundary detection. The only possibility of creating a larger error
with this method as opposed to boundary detection is in the instance
that the shape of the set is so sharp that it does not set any of the
tested points but comes from the right (i.e., uncalculated) location.
This situation is not very common.

Later, rules were added for new rows and columns that crossed each
other. In this instance you can test only four pixels. This situation
is very rare. It is hoped that it does not introduce many errors.

If multiple blocks of new lines need to be calculated there are not
reference pixels to use for solid guessing. Interlacing does the
trick. By calculating the odd lines without any guessing, the guessing
algorithm is now possible for the remaining uncalculated lines. This
simple trick saves about 30% of the calculation of the main Mandelbrot
image.

A similar approximation can also be done for the X coordinate. This
makes it possible to improve solid guessing at even pixels because all
surrounding pixels are available, further reducing errors.

@subsection Symmetry

   
   
Many fractals are horizontally or vertically symmetrical. This is
implemented in the approximation code. When there is no good
approximation available, try to mirror the opposite side if the line
is available.

This method primarily speeds up the initial image.
   
@subsection Calculation of the Mandelbrot Set

Internal Mandelbrot caluclation loop is unrolled --- it calculates
first 8 iterations using normal method and then it expects that number
of iterations will be probably large so it switches into mode, where it
calcualtes iteratins in block of 8 with one bailout test at the end.
When bailout is received, saved values from previous iterations is
restored and last 8 iterations are recalcualted slowly to get exact
values. This leps a lot especially at pentium, where conditionals in
floating point code is slow.

Another stuff is periodicity checking. XaoS has both version of loops ---
with ans without periodicity checks. In most cases it uses nonperiodicity
checking version. Periodicity check version is used just in case, some inside
set pixel has beed found during solid guessing paste around. This is done
mainly because periodicity checking verson of loop is significnatly slower.
   
@subsection Dynamic Resolution
   
The above optimizations often do not help enough and image calculation
is still too slow. One option was to reduce the framerate, but a
framerate lower than 5 frames per second is unbearable. Another option
is simply to calculate only the details that can be determined within
a time interval.

Rows/columns not calculated are simple approximated by referencing the
nearest other row/column. The result is an image with larger pixels.
One problem is the fact that the order of calculating the rows/columns
is significant. Previous versions of XaoS simply calculated all rows
from top to bottom and then columns from left to right. Using the
dynamic resolution code with this algorithm would result in distorted
images. This was solved by adding priority to every row/column and
calculating the high priority row/column first. The algorithm for
adding these priorities is as follows:
@itemize @bullet
  @item Find middle row/column of uncalculated block. Priority is the size
    of the block (in floating point coordinates)
  @item Start function for left block and right block
@end itemize
    
This function produces quite good results. It tends to make same size
rectangles on the whole image and does not depend on resolution.

Another interesting optimization is that during the zoom it is more
advantageous to calculate rows/columns in the center of the zoom
instead of the borders since these will be in the viewport longer and
the user is usually focusing on center of the zoom anyhow.

This is done by simply adding to the calculated priority
@math{normal_priority / (abs(newposition - oldposition) / step + 1)}. This
prefers rows/columns that do not move a great deal. Of course,
unzooming uses the formula reversed.

The last variable to consider is the time interval for one frame.
Setting it too low makes the calculation slow. Setting it too high
makes the framerate too low. So the amount of time spent in other
parts of the program is calculated and multiplied by 5 to determine
the interval. If time is then lower than 15FPS, 15FPS is used instead,
since slower animations are unacceptable. At the other hand if it is higher
than 35FPS, it is set to 35FPS, since higher framerate is just wasting
of computer resources. When image is not animating, this values is changed,
so framerate is choosed between 5FPS and 15FPS. This caused that images
are calcualted quickly after zooms stops.
   
@subsection Autopilot

Another interesting algorithm controls the autopilot. It is actually
quite simple. Interesting parts are found at the boundaries of the
set. It randomly looks around and zooms to the first area containing
both outside and inside set points. Some fractals (such as the Newton)
do not have points inside the set at all. In this case it selects a
point where many (more than 2) different colors are around. (i.e., It
zooms into noisy areas.)

In the instance that there are no such areas, the autopilot will
unzoom. Also detects oscilating. 

Current implementation also does detection of out of range numbers and
randomly choosed points are choosed near the old one, to avoid too often
changes of direction.

@subsection SMP support
Since version 3.0 XaoS suports SMP. This is done using threads. Most of
XaoS routines should be threaded easily --- for example moveoldpoints just
divides image into n equal part and each part is proceded by one processor.
Only unthreaded part is realloc table calculation routines. I don't see any
way to paraelize it except it calculates both - x and y approximation at one
time (using two processors).
Another interesting algorithm to paraelize is boundary trace. See comments
@code{btrace.c} for discusion about current implementation.
Only problem of current implementation I see is possibility, that calculation
is divided into too many parts (realloc tables, move points, calcualte,
symetries, dynamic resolution) and tasks needs to synchronize between each
part. So this should be too slow at real SMP box.

@node timerlib, ,algorithm ,Hacker
@section The timer library

Timer library is library I did for timming in XaoS. But I found it usefull
in many other programs (like demonstrations, games, animation players and
all other stuff that needs to be timed). So you should read this description
and possibly use it in your application and save some coding time.

There is many ways how to design of such timed aplicatioin (game)

@enumerate
@item
read user input, move badies, display and again
this way has one disadvantage. Speed of game depends on speed of computer.
This was acceptable in old times where only processor was Z80 :) but now
with wide variety of various hardwares such internal loop is unacceptable

@item
read user input, measure time since last loop and caluclate step for
badies, move badies for set step, display and again.
This way fixes problem with speed. But moving badies just for caluclated
step, that should differ a much is quite complex, usually introduces complex
calculation, floating/fixedpoint math and other unnecesarry stuff that makes
program long and introduces many bugs.

@item
Set the fixed framerate that is high enought to make game smooth but low
enought to do whole internal loop in time. So internal loop should look like:
read user input, move badies, display, meausre time spent in loop an
sleep rest of time until next frame.
This is quite popular scheme but has another disadvantage --- game can not be
designed to use whole cpu power since on slower computers internal loop should
take longer time that is reserved for one frame. Game will run slowly again.

@item
To take away disadvantage of previous methot, many games times just
moving of badies and user input. Other stuff like displaying should be
done in rest of time. In dos games moving and user input is often at
asynchronous interrupt and drawing runs as main loop. This solves problem
in case that drawing of game takes significantly longer time than moving
of badies. This is quite usual so this scheme works well.

@item
previous scheme still has one problem --- since timer interrupt works
asynchronously, there should happend many race condition, in case moving
takes longer time than time reserved from frame, computer can crash. So
this scheme should be enhanced into synchronous one with exactly same result
but avoiding problem with race condition:

read user input, measure time spent by loop and caluclate how many simulated
frame interrupts activated since last activation, if zero sleep until
simulated interrupt, move badies as many times as required, display

this is an combination of 4 and 3 and seems to be most confortable way
for writing games but since main loop is now quite complex many games don't
do that.

@item
there is still one small problem. Method 5 expect that moving takes
significantly lower time that displaying. This may not be truth. Simple
work around is to write moving routine, that should move for x moves
by faster way that calling move x times. This is often possible and makes
easy extension to scheme 5. This scheme allows you to use very large
maximal framerate (say 100FPS) and to have same results as method 2
(that is maximally exact method)
@end enumerate

As you can see, designing of main loop isn't so easy. This is just very
simple example. More advanced aplication for example should want to move
one set of badies at one framerate and other at different framerate. This
requires two such timmings. Another complication is that there is many
different ways to measure time exactly at different platforms. Under linux
you can measure using gettimeofday but under DOS this is exact just to 1/18
of second and thats too low for smooth animation and so on.

Thats why I decided to design portable easy to use timer library, that
makes easy to implement all described method, combining of them and much more.
During design I taken care at the following thinks: quality of timming,
how easy to use it is, speed, portability and to minimalize inexpected
situations (like race conditions in asynchronous interrupts and so on)

@subsection What is what

Timer library operates with @dfn{timers}. They should be created, you should
measuere time since last reset, pause them or set @dfn{handler} and @dfn{interval}.
But handler is not activat at gived interval yet. Since timer library is
not asynchronous, you must activate them.

For activating is used @dfn{groups}. You should provess group at some place in 
your program. Then all timers in group are checked and their handlers
activated if required. When time spent since last activation is higher than
interval, handler is activated more times. Also interval to next invocation is
calculated to keep freqency.  Simple scheduling is performed at handler --- handler
is activated just once and then all other timers are checked before it is activated
again. You should also define an multihandler --- handler that is activated just once
and receives argument how many intervals has left.

There is two special groups --- @code{asyncgroup}. Timers in this group are activated
asynchornously like from interrupt. It is not recomended to use it, since it
brings many problems and usually isn't required. Also it does not work at many
platforms. @code{Syncgroup} is the default group. Program is expected to process is
quite often. In case you don't need to use more groups, you should use this
one.

Time in timerlib is bit strange, since it does not flow continuously but
jumps. It is updated every time you call @code{tl_updatetime}. I used this way in
order to minimize context switches but later I found this scheme very usefull,
since you should lookup timer, do something and then reset it and don't wory
about time spend between lookup and reset since it is 0 in case you did not
called tl_updatetime. This helps to keep freqency of timers exact w/o any
errors caused by such situations. At the other hand you need to call
tl_updatetime at least once in your main loop.

Maybe you don't know why to create more groups, but I found it quite usefull.
For example an autopilot in XaoS has such special group --- I need to call it
approx. every 1/20 of second but just at one place in program. Invoking of
autopilot when caluclation is active should produce incorrect results, so I
have special group for autopilot and process just at one place where I am sure
it is safe. 

Timers should be also emulated. You should stop them and then control flow of
time for given timer. This should be quite usefull for example when you want
precalculate animation at given framerate.

@subsection Time functions

@deftypefn Function void tl_update_time (void)
Update time used by timerlib. This must be called at least once in main loop
otherwise time will not flow. See above.
@end deftypefn
@deftypefn Function void tl_sleep (int @var{time})
Sleep given time. Similiar to usleep at POSIX.
@end deftypefn
@subsection Group functions

@deftypefn Function tl_group *tl_create_group (void)
Allocate and initialize group header. Returns NULL when malloc fails.
@end deftypefn
@deftypefn Function void tl_free_group (tl_group *@var{group})
Free memory storage used by group structure
@end deftypefn
@deftypefn Function int tl_process_group (tl_group *@var{group}, int *@var{activated})
Process timers in group and activates their handlers. Returns time
until next invocation. Main loop should sleep returned time
then. An @var{activated} parameter sould be @code{NULL}. If it is non @code{NULL}, variable
is set to number of activated handlers.
@end deftypefn
@subsection Timer functions

@deftypefn Function tl_timer *tl_create_timer (void)
Create timer structure.
@end deftypefn
@deftypefn Function void tl_free_timer (tl_timer *@var{timer})
Free memory storage used by timer structure
@end deftypefn
@deftypefn Function void tl_reset_timer (tl_timer *@var{timer});
Reset timer to current time. (time of last actication of @code{tl_update_time})
@end deftypefn
@deftypefn Function int tl_lookup_timer (tl_timer *@var{timer});
Return time since last call of tl_reset_timer or last activation of handler.
@end deftypefn
@deftypefn Function void tl_set_interval (tl_timer *@var{timer}, int @var{interval});
@end deftypefn
@deftypefn Function void tl_set_handler (tl_timer *@var{timer}, void (*@var{handler}) (void *),void *userdata);
@end deftypefn
@deftypefn Function void tl_set_multihandler (tl_timer *@var{timer}, void (*@var{handler}) (void *,int),void *userdata);

Handler, multihandler and interval control functions
@end deftypefn


@deftypefn Function void tl_add_timer (tl_group *@var{group}, tl_timer *@var{timer})
Add timer to given group. Timer should be added into just one group.
@end deftypefn
@deftypefn Function void tl_stop_timer (tl_timer *@var{timer})
@end deftypefn
@deftypefn Function void tl_resume_timer (tl_timer *@var{timer})
Stop and resume timer.
@end deftypefn

@deftypefn Function void tl_slowdown_timer (tl_timer *@var{timer},int @var{time})
Time in timer is moved back for given time.
@end deftypefn

@subsection Example main loop

@example
while(1)
@{
  time=tl_process_group(syncgroup,activated); /*Call game control functions*/
  update_keys();
  if(activated) /*something changed*/
    display();
  else tl_sleep(time);
@}
@end example

@bye
