UVE140R

**UVE140R** is a .ZIP file that you can decompress made by InterAction STUDIOS. This folder has other four compressed folders , two .UVW files, a readme, seven .TXT files, and two .EXE files.

# CHANGES.TXT

Changes history

v1.40

ú    Added 3RD.PAS as an example of simple sprite movement.
ú    Added UVE\_KEY (keyboard handling) unit to the registered version of UVE.
ú    There is now full Turbo Pascal v6.0 support.
ú    Changed BENCH.EXE to correct some timing problems with very fast
systems.
ú    Removed WordPerfect and MS-Word formats from the registered version of
UVE.  WordPerfect conversion did not work correctly and MS-Word can load RTF
files anyway.
ú    Registration section completely rewritten.  It is now possible to
register via credit card.
ú    All supporting utilities now assume the default extension if none is
specified.
ú    Added UVE mailing list information.
ú    (There are no changes to the UVE32 kernel unit.)

v1.38

ú    First public release.

# CONTACT.TXT

Contacting InterAction software

You can contact me for any reason, whether it's to ask for registration
information, to ask if/how you can do something in UVE32, to report a bug,
or just to say what you like/don't like about UVE32.  Alternatively, you
can join the UVE mailing list (more information in the relevant section).

When writing in to report a bug or ask something about a command, please
take the time to read through the manual.  There is a good chance the
answer you are looking for is already there.  Also, check the FAQ for
answers to frequently asked questions.  When you writing in with a
question, please include in your mail information about the version of
UVE32 you are using.

Okay, by far the best way to contact me is through e-mail.  My address is:

 cbp@doc.ic.ac.uk

Note that this address is only valid until the 1st of July, 1998.
Furthermore, avoid sending mail to that address during the Christmas,
Easter, and Summer holidays as I will not be checking my mail regularly
during those times.  You can alternatively send mail to the following
address:

   robin@hol.net

It's probably A Good Idea to send your mail to both addresses to minimize
latency time (I love it when I use jargon).  Some e-mail bounces, so if
you haven't heard from me in 15 days, send your mail again, perhaps
including more complete or alternative reply addresses.

If you have no access to the Internet, You can use conventional surface
mail, although I can't guarantee how long it's going to take before you
get an answer.  You can write to:

Constantine Prouskas
4 Adrianoupoleos street
 GR 156-69 Papagou
  Athens, GREECE

# FILE\_ID.DIZ

Ultra VGA Engine 32 version 1.40
(c)MCProusk/InterAction software

Sprites,tiles,virtual worlds,PCXs,
scrolling/static backgrounds,FLIs,
transparency,translucency,windows,
palettes,wad files and much more!

# LICENSE.TXT

License Agreement

InterAction software grants you the right to use Ultra VGA Engine 32
("UVE32").  For purposes of this section, "use" means loading UVE32 into
RAM, as well as installation on a hard disk or other storage  device.

You may use the shareware version of UVE32 for a period of 21 days, after
which you must either delete it or obtain the registered version.

You may freely distribute, transmit and store the shareware version of UVE32
on any electronic media, including but not limited to floppy diskette, hard
disk, CD-ROM or other storage device, provided that you do not remove, edit,
modify, or otherwise alter the original files of UVE32.  You may not
distribute the registered version of UVE32.

You may not modify, translate, disassemble, decompile, reverse engineer or
create derivative works (excluding software that uses UVE32 directly) based
upon UVE32.

You may use UVE32 in your own software, provided that you have complied with
the registration requirements set forth by InterAction software.  You may
not use the shareware version of UVE32 in any piece of software that will
become publicly available, including but not limited to public domain,
freeware, shareware and commercial/retail software.

UVE32 is copyrighted by InterAction software and is protected by
international copyright laws and international treaty provisions.  You must
treat UVE32 like any other copyrighted material.  You
agree to use your best efforts to see that any user of UVE32 licensed
hereunder complies with this agreement.

This software and accompanying written materials (including instructions for
use) are provides "as is" without warranty of any kind. Further, InterAction
software does not warrant or make any guarantees representations regarding
the use, or the results of use, of the software or written materials in
terms of correctness, accuracy, reliability, currentness, or otherwise. The
entire risk as to the results and performance of the software is assumed by
you.

The above is the only warranty of any kind, either expressed or implied,
including but not limited to, implied warranties of merchantability or
fitness for a particular purpose.  In any case, InterAction software shall
not be liable for any direct, indirect, consequential or incidental damages
(including damages for loss of business profits, business interruption, loss
of business information and loss of data) arising out of the use or
inability to use UVE32, even if InterAction software has been advised of the
possibility of such damages.

You acknowledge that you have read this agreement, you understand this
agreement, and understand that by continuing the installation of UVE32, by
loading or running UVE32, or by placing or copying UVE32 onto your computer
hard drive, you agree to be bound by this agreement's terms and conditions.

# REGISTER.TXT

Registering

UVE32 is shareware.  It is not free.  If you use UVE32 for 21 days and
wish to continue using it, you must register it.  Read the License
Agreement for more information on what you are and are not allowed to do.
By registering you are acknowledging all he work that has gone behind this
product and supporting further development.

By registering, you get:

ú    My eternal gratitude :-)
ú    The latest version of UVE32 for Turbo Pascal 6.0 & 7.0, plus the
protected mode version for Borland Pascal 7.0.
ú    Unlimited mail/e-mail support (including hot tips on how it's
possible to have a 2-player split screen in UVE32).
ú    The complete documentation in Rich Text Format (.RTF), complete with
advanced formatting and tables.
ú    Registered versions of all the supporting utilities, including
UVSINFO, PCX2UVS, PCX2UVT, LIBMAKER.
ú    An advanced, powerful version of PCX2UVS that allows multiple sprites
per PCX and complete control over the save region.
ú    WADMAKER:  An extra utility that can create .UVW files.
ú    WADVIEW:  An extra utility that shows the contents of .UVW files.
ú    FLI2UVL:  An extra utility that directly creates a UVL file from a
FLI file.
ú    \*NEW!\* UVE\_KEY: A unit to handle multiple keypresses.  An absolute
must for games.

Registration is US$25.  There is a 20% discount to any cheque or cash
orders (amount after discount = US$20).

Starting with v1.40, it is now possible to register using your credit
card.  Since this has made things a bit more complicated, I have split up
the registration to credit card and non-credit card orders.

Credit card orders

For your convenience, I have contacted another company, NorthStar
solutions, to process any orders you may wish to place with your Visa,
MasterCard or Discover card.  NorthStar Solutions can be easily contacted
for orders only via any of the following methods:

ú    PHONE ORDERS
Available 10am-8pm, EST, Monday through Saturday
1-800-699-6395 (Calls from the U.S. only.)
1-803-699-6395 (Calls from outside the U.S.)

ú    FAX ORDERS
1-803-699-5465 (Available 24 hours.  International and business orders
encouraged.)

ú    INTERNET ORDERS
Simply fill out the online order form at
http://ourworld.compuserve.com/homepages/starmail

ú    E-MAIL ORDERS
You can send your order via e-mail to:
America Online: STARMAIL
CompuServe: 71561.2751
Internet: 71561.2751@compuserve.com

Please provide (or be prepared to provide) the following information when
ordering:
ú    The program you are registering (Ultra VGA Engine 32).
ú    Your mailing address.
ú    Your Visa, MasterCard or Discover card number and its expiration
date.
ú    Your drive type (if other than 3.5").
ú    Your e-mail address (so that NorthStar Solutions can send you
confirmation of your order).

IMPORTANT!
Please note that NorthStar Solutions only handles credit card orders.
They will not be able to offer any assistance or technical support with
any problems you may have with UVE32.  Please refer any such problems to
me directly.

Feel free to e-mail me as well, notifying me that you placed an order with
NorthStar Solutions if you want to speed up the sending out of the disk.

Other (non-credit card) orders

Apart by using a credit card, you can also register by the following
alternative methods:

ú    Cheque.  Must be in U.S. Dollars, British Pounds or Greek Drachmas
and made payable to "Constantine Prouskas".
ú    Cash.  Again, must be U.S. Dollars, British Pounds or Greek Drachmas.
For other currencies, visit your local bank or travel exchange.  You
should be able to convert to one of the above currencies using
international exchange rates.
ú    Direct deposit in a bank account (U.S., UK or Greece only).

Since addresses, bank accounts and the like are subject to change,
however, it's best if you contact me at the above address first (see the
"Contacting InterAction software" section).  Apart from notifying me that
you want to register, it is possible to work out the payment method that
is most convenient on a case-by-case basis (even using a method not
described above).  Additionally,  I can arrange sending out the registered
version via e-mail, if you so wish.

# SITES.TXT

Where can I get UVE32?

The two primary sites where the lastest version of UVE32 will be uploaded
first are:

ú    The SimTel archive in the US (ftp to ftp.simtel.com or ftp.cdrom.com)
in simtelnet/msdos/turbopas
ú    The X2 archive in Finland (ftp to x2ftp.oulu.fi) in
msdos/programming/libs/

Of course, since everybody mirrors everybody else these days, it should soon
spread to just about everywhere.  If you cannot access these sites, try
getting UVE32 from a nearby mirror site.  At the time of this writing, the
Country             Host                          Directory
Argentina           ftp.satlink.com               /pub/mirrors/simtelnet
Australia           ftp.bhp.com.au                /pub/simtelnet
Australia           ftp.iniaccess.net.au          /pub/simtelnet
Australia           ftp.tas.gov.au                /pub/simtelnet
Australia           sunsite.anu.edu.au            /pub/pc/simtelnet
Austria             ftp.univie.ac.at              /mirror/simtelnet
Belgium             ftp.linkline.be               /mirror/simtelnet
Belgium             ftp.tornado.be                /pub/simtelnet
Bulgaria            ftp.eunet.bg                  /pub/simtelnet
Brazil              ftp.iis.com.br                /pub/simtelnet
Brazil              ftp.unicamp.br                /pub/simtelnet
Canada,Ottawa       ftp.crc.doc.ca                /systems/ibmpc/simtelnet
Canada,Vancvr       ftp.direct.ca                 /pub/simtelnet
Chile               sunsite.dcc.uchile.cl         /pub/Mirror/simtelnet
China               ftp.pku.edu.cn                /pub/simtelnet
Czech Republic      ftp.eunet.cz                  /pub/simtelnet
Czech Republic      pub.vse.cz                    /pub/simtelnet
Czech Republic      ftp.zcu.cz                    /pub/simtelnet
Finland             ftp.funet.fi                  /mirrors/ftp.simtel.net/pub/simtelnet
France              ftp.grolier.fr                /pub/simtelnet
France              ftp.ibp.fr                    /pub/simtelnet
Germany             ftp.mpi-sb.mpg.de             /pub/simtelnet
Germany             ftp.rz.ruhr-uni-bochum.de     /pub/simtelnet
Germany             ftp.tu-chemnitz.de            /pub/simtelnet
Germany             ftp.uni-heidelberg.de         /pub/simtelnet
Germany             ftp.uni-magdeburg.de          /pub/mirrors/simtelnet
Germany             ftp.uni-paderborn.de          /pub/simtelnet
Germany             ftp.uni-trier.de              /pub/pc/mirrors/simtelnet
Germany             ftp.rz.uni-wuerzburg.de       /pub/pc/simtelnet
Greece              ftp.ntua.gr                   /pub/pc/simtelnet
Hong Kong           ftp.cs.cuhk.hk                /pub/simtelnet
Hong Kong           ftp.hkstar.com                /pub/simtelnet
Hong Kong           sunsite.ust.hk                /pub/simtelnet
Israel              ftp.huji.ac.il                /pub/simtelnet
Italy               cis.utovrm.it                 /simtelnet
Italy               ftp.flashnet.it               /pub/simtelnet
Italy               ftp.unina.it                  /pub/simtelnet
Italy               mcftp.mclink.it               /pub/simtelnet
Japan               ftp.iij.ad.jp                 /pub/simtelnet
Japan               ftp.riken.go.jp               /pub/simtelnet
Japan               ftp.saitama-u.ac.jp           /pub/simtelnet
Japan               ftp.u-aizu.ac.jp              /pub/PC/simtelnet
Japan               ring.aist.go.jp               /pub/simtelnet
Japan               ring.asahi-net.or.jp          /pub/simtelnet
Latvia              ftp.lanet.lv                  /pub/mirror/simtelnet
Malaysia            ftp.jaring.my                 /pub/simtelnet
Malaysia            ftp.mimos.my                  /pub/simtelnet
Mexico              ftp.gdl.iteso.mx              /pub/simtelnet
Netherlands         ftp.euro.net                  /d5/simtelnet
Netherlands         ftp.nic.surfnet.nl            /mirror-archive/software/simtelnet
New Zealand         ftp.vuw.ac.nz                 /pub/simtelnet
Norway              ftp.bitcon.no                 /pub/simtelnet
Poland              ftp.cyf-kr.edu.pl             /pub/mirror/Simtel.Net
Poland              ftp.icm.edu.pl                /pub/simtelnet
Poland              ftp.man.poznan.pl             /pub/simtelnet
Portugal            ftp.ip.pt                     /pub/simtelnet
Portugal            ftp.ua.pt                     /pub/simtelnet
Romania             ftp.sorostm.ro                /pub/simtelnet
Singapore           ftp.nus.sg                    /pub/simtelnet
Slovakia            ftp.uakom.sk                  /pub/simtelnet
Slovenia            ftp.arnes.si                  /software/simtelnet
South Africa        ftp.is.co.za                  /pub/simtelnet
South Africa        ftp.sun.ac.za                 /pub/simtelnet
South Korea         ftp.nuri.net                  /pub/simtelnet
South Korea         ftp.sogang.ac.kr              /pub/simtelnet
South Korea         sunsite.snu.ac.kr             /pub/simtelnet
Spain               ftp.rediris.es                /mirror/simtelnet
Sweden              ftp.sunet.se                  /pub/simtelnet
Switzerland         ftp.switch.ch                 /mirror/simtelnet
Taiwan              ftp.ncu.edu.tw                /Packages/simtelnet
Taiwan              nctuccca.edu.tw               /mirror/simtelnet
Thailand            ftp.nectec.or.th              /pub/mirrors/simtelnet
UK, Edinburgh       emwac.ed.ac.uk                /mirrors/simtelnet
UK, London          ftp.demon.co.uk               /pub/simtelnet
UK, Lancaster       micros.hensa.ac.uk            /pub/simtelnet
UK, London          sunsite.doc.ic.ac.uk          /packages/simtelnet
US, California      ftp.cdrom.com                 /pub/simtelnet
US, California      ftp.digital.com               /pub/micro/pc/simtelnet
US, Illinois        uiarchive.cso.uiuc.edu        /pub/systems/pc/simtelnet
US, Mass.           ftp.bu.edu                    /pub/mirrors/simtelnet
US, Michigan        oak.oakland.edu               /pub/simtelnet
US, New York        ftp.rge.com                   /pub/systems/simtelnet
US, Oklahoma        ftp.ou.edu                    /pub/simtelnet
US, Oregon          ftp.orst.edu                  /pub/simtelnet
US, Utah            ftp.cyber-naut.com            /pub/simtelnet
US, Virginia        mirrors.aol.com               /pub/simtelnet

For the X2 archive:

Site: ftp.ibp.fr (France)
Path: /pub/pc/x2ftp/
Mirror: books,msdos
Update: 0330 GMT

Site: ftp.rz.uni-karlsruhe.de (Germany)
Path: /pub/programming/mirror.x2ftp/
Mirror: books,msdos,unix
Update: 0200 GMT

Site: ftp.infomagic.com (USA)
Path: /pub/mirrors/x2ftp/
Mirror: amiga,books,console,msdos,standards
Update: 0400 GMT

Site: illusion.shiny.it (Italy)
Path: /pub/x2ftp/
Mirror: msdos
Update: 0500 GMT

Site: mirrors.aol.com (USA)
Path: /pub/x2ftp
Mirror: books,console,msdos
Update: 2330 GMT

Site: ftp.ee.techpta.ac.za (168.172.8.5) (South Africa)
Path: /pub/mirrors/x2ftp/
Mirror:
Update: 2300 GMT

Site: ftp.lanet.lv (Latvia)
Path: /pub/mirror/x2ftp/
Mirror: books,msdos
Update: 0130 GMT

Site: http://www2.cp.eng.chula.ac.th/mirror1/x2ftp
Mirror: msdos
Update: 2100 GMT
Freq.: weekly (Friday)
Admin: ftpadm@cpu.cp.eng.chula.ac.th

# UVE32.TXT

Ultra VGA Engine 32
   Version 1.40

(c)Copyright 1996 Constantine Prouskas
InterAction software

Prologue                                                3
Quickstart                                              3
Requirements                                            3
What's UVE32?                                           3
License Agreement                                       4
Technical Information                                   5
UVE Theory                                              6
Frames                                                6
Pages                                                 7
The VGA page                                         7
The Hidden page                                      7
The Background page                                  7
The Tiles page                                       7
Sprites                                               8
Loading sprite images                                8
Displaying a sprite                                  9
Sprite Chaining                                     10
Moving sprites                                      10
Sprite collision                                    11
Deleting sprites & images                           11
Other sprite attributes                             12
Palettes                                             12
Palette maps                                         13
Tiles                                                13
PCXs                                                 14
Fonts                                                14
FLIs                                                 15
WAD files                                            15
UVE Interface                                          16
Unit interface section                               16
Other variables                                      17
Functions & Procedures                               17
General Purpose Commands                            17
Beginner Commands                                   18
Intermediate Commands                               21
Advanced Commands                                   25
Supporting Utilities                                   30
UVSINFO                                              30
PCX2UVS                                              30
PCX2UVT                                              30
LIBMAKER                                             30
Known bugs... err.. features                           31
UVE32 Frequently Asked Questions                       31
Where can I get UVE32?                                 31
Contacting InterAction software                        34
UVE mailing list                                       34
Registering                                            34
Credit card orders                                   35
Other (non-credit card) orders                       36
Epilogue                                               36

Prologue

Right off the bat, I'd like to clear up some things:

ú    Version 1.40 is the second public release of UVE32 and, as such, is
still prone to various bugs and errors.  I've been using UVE32 for more
than two years now and everything is pretty much ironed out, but I wrote
it, and I'm sure someone out there will try something I had never thought
of and crash it.  So, if you encounter any bugs, please report them to me
and I will correct them in the next release.  Read the section on
contacting InterAction software for further info.

ú    UVE32 is shareware.  Try before you buy.  And we all know what that
means.  If you like UVE32 and continue to use it, you must register it.
Registering not only clears your conscience, but also entitles you to free
updates, loads of utilities and support.  Read the section on registering
for more information.

Quickstart

For those of you who are really, really in a hurry, take these steps to
get you started:

ú    Unzip UVE32.
ú    Run BENCH.EXE to see if your VGA is fast enough for UVE32 animation.
ú    Run UVEDEMO.EXE for an example of UVE32's capabilities.
ú    Load up Pascal and run the examples provided.
ú    Off you go!

Requirements

What you need to run UVE32:
ú    A computer.  I guess you have one of those already.  Must be at least
a 386, though, because of the 32-bit code.  Not much of a limitation, if
you ask me.
ú    A VGA card.  The faster the better.
ú    Turbo Pascal v6.0 or Borland/Turbo Pascal v7.0.

That's it.

What's UVE32?

Let's start with the easy stuff.  UVE32 is a sprite-based graphics &
animation unit for Turbo Pascal 6.0 & Borland/Turbo Pascal 7.0.  Drop to
DOS and run BENCH.EXE and UVEDEMO.EXE to see an example of  what this baby
can do.

UVE32 stands for Ultra VGA Engine 32-bit.  Ultra is there to distinguish
UVE32 from the VGA Engine series, which is a set of three older libraries
(VENGINE, VENGINE2 and VENGINE3).  UVE32 has been rewritten from scratch,
using a different animation algorithm.  VGA because UVE32 supports only
the VGA (CGA support is on the way ;-).  Engine because it provides the
horsepower for an animation-intensive application, i.e. (who am I trying
to fool) GAMES. 32 because it contains 32-bit code and is capable of
running in protected mode. For the time being, 32 bit code is more or less
useless because of Borland's 16-bit compiler, but is included for when a
decent 32-bit compiler is released.

Here's a quick run-down of UVE32's features before we get started.

ú    runs in VGA 320x200 256 colors
ú    500 simultaneously active sprites
ú    32K maximum sprite dimension (width/height)
ú    64K maximum single sprite size
ú    sprite chaining
ú    sprite collision detection
ú    automatic memory management
ú    virtual coordinates in the -32K...+32K range
ú    animation window
ú    14 loadable fonts
ú    static or scrolling background
ú    transparency
ú    translucency
ú    palette maps
ú    palette cross-fades
ú    PCX support
ú    FLI support
ú    WAD file support

In my experience, sprite libraries can be divided into the following
categories:

ú    Easy to use (i.e., slow)
ú    Powerful (i.e., extremely user-unfriendly)
ú    Fast and user friendly (and written in C)

UVE32 offers an easy to use interface as well as low-level routines for
squeezing out that last bit of potential.  If you are a beginner, you will
find the interface very simple to use.  If you are more advanced, you will
not be held back by the inherent limitations that inevitably come with
easy user interfaces.

UVE32 might not run well on your system, depending on your VGA card.  If
you are one of those people that read the documentation before running
every executable in sight (fat chance), I suggest you drop to DOS and run
the demonstration and the benchmarking program to discover if everything
runs as expected.  Unless your VGA is a painfully slow one, however, I
don't expect you will run into any difficulties.

Before we get into the intricacies of UVE32, take a moment to read the
License Agreement, which contains some important information concerning
the use of  UVE32.

License Agreement

InterAction software grants you the right to use Ultra VGA Engine 32
("UVE32").  For purposes of this section, "use" means loading UVE32 into
RAM, as well as installation on a hard disk or other storage  device.

You may use the shareware version of UVE32 for a period of 21 days, after
which you must either delete it or obtain the registered version.

You may freely distribute, transmit and store the shareware version of
UVE32 on any electronic media, including but not limited to floppy
diskette, hard disk, CD-ROM or other storage device, provided that you do
not remove, edit, modify, or otherwise alter the original files of UVE32.
You may not distribute the registered version of UVE32.

You may not modify, translate, disassemble, decompile, reverse engineer or
create derivative works (excluding software that uses UVE32 directly)
based upon UVE32.

You may use UVE32 in your own software, provided that you have complied
with the registration requirements set forth by InterAction software.  You
may not use the shareware version of UVE32 in any piece of software that
will become publicly available, including but not limited to public
domain, freeware, shareware and commercial/retail software.

UVE32 is copyrighted by InterAction software and is protected by
international copyright laws and international treaty provisions.  You
must treat UVE32 like any other copyrighted material.  You
agree to use your best efforts to see that any user of UVE32 licensed
hereunder complies with this agreement.

This software and accompanying written materials (including instructions
for use) are provides "as is" without warranty of any kind. Further,
InterAction software does not warrant or make any guarantees
representations regarding the use, or the results of use, of the software
or written materials in terms of correctness, accuracy, reliability,
currentness, or otherwise. The entire risk as to the results and
performance of the software is assumed by you.

The above is the only warranty of any kind, either expressed or implied,
including but not limited to, implied warranties of merchantability or
fitness for a particular purpose.  In any case, InterAction software shall
not be liable for any direct, indirect, consequential or incidental
damages (including damages for loss of business profits, business
interruption, loss of business information and loss of data) arising out
of the use or inability to use UVE32, even if InterAction software has
been advised of the possibility of such damages.

You acknowledge that you have read this agreement, you understand this
agreement, and understand that by continuing the installation of UVE32, by
loading or running UVE32, or by placing or copying UVE32 onto your
computer hard drive, you agree to be bound by this agreement's terms and
conditions.

Technical Information

NO!  NO!  NO!  I said READ the License Agreement, not SKIP OVER it!  As
boring as it sounds, you must read it before using UVE32.  You have?
That's OK, then.  Let's get moving.

Note:  This section contains, as the heading would suggest,  technical
information.  You do not need to know anything contained in this section
to use UVE32.  Instead, it's meant to provide some insight at how UVE32
works.  If you haven't got any experience with the VGA and the VGA
hardware, it's best to skip this section altogether.

UVE32 runs in the standard VGA mode 0x13 (19 to you ten-fingered people).
That's your average 320x200 256-color mode supported by the BIOS in every
VGA since, well, the EGA.  Okay, so it's only got one page and an odd
aspect-ratio, but when it comes to rock-solid animation and simple code
(the latter bearing the most weight for me personally), the fact is, you
can't beat mode 0x13's non-banked linear bitmap organization.

UVE32 is based on a, for lack of a better term, page-copy algorithm.  To
those of you familiar with dirty-rectangle animation, you can think of the
whole screen as being a single dirty rectangle, updated each frame.  What
does this mean?  It means that all preparation for a frame is done in non-
displayable system memory area the same size as the screen (a "page").
Once the whole frame is complete, the "hidden" page is simply copied onto
the visible screen.  You might think copying the whole screen every frame
is overkill; and you'd be right (didn't expect me to say that, did you?),
but only in light load conditions.  In heavy load conditions and in cases
where the whole screen changes from frame to frame (such as in panning
around a virtual background), this is much faster than trying to maintain
a list of updated areas and optimizing it so that each pixel is drawn once
and only once.

I'd like to take a moment to point out that when I came up with this sort
of algorithm, I didn't have a clue about page-flipping (or any other
animation technique, for that matter), and it seemed like the intuitive
thing to do.  I have to admit, though, that, even now, I would be hard
pressed to find another algorithm that can deliver flawless frames given
an adequately fast VGA.  Also, a little known fact is that page-flipped
modes are built around the VGA's vertical sync/retrace signal, which
cannot be relied upon, because there is no specification about exactly
when it should occur.  Some of the other page-flipped libraries around
flickered hideously when I ran them on my computer.

All drawing is done in system memory, which is much faster that video
memory.  Since the image has to be copied to video memory in the end,
however, video memory speed becomes the ultimate bottleneck, and, believe
me, a narrow bottleneck it is.  On my slow ISA VGA, video access takes 50%
of a 50-ms frame.  It can get much worse than this, though.  Some VGAs in
my university lab (no names, please) take more than 500ms to copy the page
onto display memory.  FIVE HUNDRED milliseconds for a maximum of under 2
frames per second!  You need not worry if you have a local bus VGA,
however, and I've found that all Trident-based cards I've tested peak at
about 20fps, which btw is fine for animation.  On a typical 486-33 with a
local bus VGA, a sustained rate of 35-40 frames per second is not
extraordinary.

Apart from the VGA access time bottleneck, another potential problem is
shearing.  Shearing occurs when the VGA is scanning displayable data while
the CPU is copying from the hidden page to the visible page.  Let's just
say for a second that the CPU cannot copy data as fast as the electron
beam sweeps the screen (usually 70Hz).  Let's also assume that the
electron beam starts scanning when the CPU is halfway through copying
data, and that it catches up with the CPU at some point within the
displayable data area.  Everything displayed up to that point will belong
to the new frame, and everything below will belong to the old frame, since
the CPU hasn't had a chance to update it yet. The result will be a frame
composed of parts of two different frames.

Shearing is bad, but not as bad as you might think.  It is only noticeable
on a slow VGA, with a continuously scrolling background of specific
pattern types and even then, it registers as some sort of flicker (not the
type you're used to, just some sort of color dimming at specific scanlines
of the screen).  Shearing is inherent to beam scanning anyway, since the
screen is not updated all at the same instant.  If your VGA is capable of
copying the whole page in the 70Hz time window, then shearing should not
pose a problem.  In my experience, you can only see it when a disk caching
program kicks in and writes to disk during the memory move (btw, in UVE32,
interrupts are not disabled during a memory move).

UVE Theory

Frames

Note:  This section, despite being the basis of everything else, contains
a lot of forward references.  If you don't understand what's going on,
simply go on and come back once you've read the rest of the UVE32 theory.

Frames are the building blocks of animation.  They are the same type of
frames used in traditional cinema and television animation.  A typical
UVE32 frame cycle goes as follows:
ú    First, the background is copied onto the workarea (the hidden page),
erasing everything from the previous frame.
ú    The scrolling background, if enabled, is constructed and placed on
top of the background.
ú    The sprites are copied, with sprite 500 going first and sprite 1
last.  This means that, as viewed on the screen, sprite 1 is on top and
sprite 500 is at the very bottom.
ú    The frame is now complete and is made visible on the screen.
ú    If there is still time, UVE32 waits until the extra time expires
before starting on the next frame.

I didn't know when I first built UVE32, but the same frame technique is
used by Mortal Kombat and Quake (in videomode 0).  It's the most efficient
way to do animation when the whole screen changes from frame to frame.  If
you know of any more games that use this technique, I'd like to hear from
you.

Related functions:
procedure ia\_waitretrace;
procedure ia\_doframepart1;
procedure ia\_doframepart2;
procedure ia\_doframepart3;
procedure ia\_doframe;
procedure ia\_setcycletime (i:integer);

Pages

A page is simply a region of memory that can hold a 320x200 image
(actually it's a bit more that that, but who's counting).  UVE32 has 4
predefined pages, on top of which you can declare your own, should that be
necessary.  These are:

The VGA page

The vga page is the only page of the four that is visible to the user.
This page holds the contents of the visible screen, and any change to that
page will be immediately visible.

The Hidden page

The hidden page is where virtually all work takes place.  To avoid all
complications relating to updating the vga page in real time, the frame is
first prepared in the hidden page and, once it is complete, is copied onto
the vga page, thus becoming visible.

The Background page

The background page holds, rather unsurprisingly, the background image.
At the beginning of each frame the background page is copied onto the
hidden page to erase everything that was previously there and start fresh
for the new frame.

The Tiles page

The tiles page is not used for drawing, but is rather an area of memory
that tiles are stored in.  It can hold up to 255 16x16 tiles.  Note that
this page is not automatically allocated, as it is not needed if there is
no scrolling background.  UVE32 will automatically allocate this page once
ia\_setscrolling (which enables a scrolling background) is called.

Related functions:
procedure ia\_copypage (source,dest:word);
procedure ia\_putpixel (where,x,y:word;c:byte);
function ia\_getpixel (where,x,y:word):byte;
procedure ia\_hline (where:word;x,y,len:integer;c:byte);
procedure ia\_vline (where:word;x,y,len:integer;c:byte);
procedure ia\_line(where:word; x1,y1,x2,y2:integer;color:byte);
procedure ia\_box (where:word;x1,y1,x2,y2:integer;c:byte;filled:boolean);
procedure ia\_box\_clip
(where:word;x1,y1,x2,y2:integer;c:byte;filled:boolean);
procedure ia\_cls (where:word;col:byte);
procedure ia\_fadein (where,time:word);
procedure ia\_newpage (var p:pagepointer; var where:word);

Sprites

A sprite is, simply put, an animated graphic object on the screen.  An
example to illustrate: in PAC-MAN, both the thing the player controls
(moves) around the maze (that yellow circle with the big mouth; I suppose
it's called the "pac-man") and the ghosts are sprites, in the sense that
they are movable entities separate from something static like the
background.

Now, I must confess that if this is the first time you hear about sprites,
you are probably totally confused by my explanation; and anyone short of a
nuclear scientist would be.  The best solution is to run some of the
examples included with UVE32 to get an intuitive idea about what sprites
are.  For the rest of this discussion, I will assume that you understand
the word sprite has nothing to do with fairies or pixies in this context.
(Although, just to confuse you more, it is possible to have a sprite that
looks like a fairy.  On second thought, forget I just said that.)

A sprite is an object that has coordinates (so it can move around) along
with some other attributes, the most important of which is what it looks
like; that is, what it's physical representation on the screen is.  A
sword, a dragon, a monster, all these are different sprites in the sense
that what you see on the screen can be uniquely identified by its
appearance.  Often the term sprite is used to refer to the picture that is
visible on the screen, but that's not what I am going to follow, because
beginners will get completely lost.

To recap:  A sprite is an object that has coordinates along with other
attributes, and which is linked to its image, its likeness, its semblance,
which is a picture that is used to represent that sprite on the screen.
That picture is not necessarily unique.  For example, ten swords displayed
on the screen are ten different sprites, in the sense that each one is
individually controllable.  However, they are all linked to the same
image.  They are ten different objects with a common appearance on the
screen.

I will use the term "sprite" when referring to an object and the term
"image" when I am referring to the picture that represents the sprite.

The reason the sprite is different from its image is memory constraints.
Imagine 100 identical swords displayed on the screen.  Clearly, to store
the same image 100 times along with each sprite would be clearly a waste
of memory space.  We therefore separate the image from the sprite, and
from within the sprite structure, we select one of the available images to
represent it.

Loading sprite images

Okay.  Before an image can be used, it must first be loaded into memory.
In UVE32, there are 500 slots (positions) for images to be placed in, from
1 to 500 (0 has a special meaning, as we will soon see).  Each slot can be
thought of as a pigeon-hole that can hold a single image.  Let's say
there's a file called "pacman.uvs" that contains an image  and you want to
load it into slot 7.  You don't need to worry about memory allocation and
the like, you just say

ia\_loadspr ('pacman.uvs',7);

Note that, although the function name is ia\_loadspr, it doesn't load a
sprite (sprites cannot be "loaded" in the normal sense); it loads an
image.  At this point it might be a good idea to refer to the examples to
see how images are loaded.

A slight digression:  .UVS files hold a single sprite image, whereas .UVL
files hold multiple images that are loaded into consecutive locations.
UVE32 automatically detects whether a given file holds a single or
multiple images, so you don't need to stick to the extensions (but it's
better if you do, because some UVE32 utilities assume default extensions).

It is important to realize that loading an image into memory does not
display it on the screen in any way. This is so important it bears
repeating.  Loading an image does not cause anything to be displayed on
the screen.  You are simply loading an image and putting it into one of
the 500 available slots.  The number of the image's slot is the image's
id; the way in which it will be referred to when you want to use it.
Continuing the example above, every time you want to use the image
'pacman.uvs', you will refer to it by using the number 7, the number of
it's slot.

As a sidenote, UVE32 sprites are use a proprietary RLE & zero-byte variant
compression method for fast rendering.  This offers great performance but
screen-space clipping is hell.  I definitely wouldn't recommend it to the
faint-hearted :-)

Related functions:
procedure ia\_loadspr (filename:string; n:integer);

Displaying a sprite

Now that the image has been loaded, we need to define a sprite and link it
to that image.  Up to 500 sprites can be simultaneously defined (ranging
from 1 to 500).  As mentioned earlier, defining a sprite is as simple as
linking it to an image, so it possesses an external, physical
representation and therefore is able to be displayed.  This is easily
done, if we remember that each image has it's own unique slot number.

A sprite is defined by linking it to an image.  As soon as a sprite is
linked to an image, it is displayed (not instantly, though; you have to
wait until a frame occurs).  Sprites are held in an array of 500 elements,
with each item being a single sprite.  This array is called spr.  So, if
we want to access the 10th sprite we would do something along the lines of

with spr[10] do
begin
...
end;

So, how do we link the image with the sprite?  Couldn't be easier.  No,
really.  Simply set the n field of the sprite in question to the number of
the image slot.  So, from above, if the pacman is loaded into slot 7:

with spr[10] do
begin
n:=7;
end;

or simply:

spr[10].n:=7;

Done!  Now, in the next frame, the sprite will appear at (0,0) screen
coordinates.  Of course, in a real application, some of the other fields
should be set accordingly.  A sprite is disabled (not displayed) by
setting the n field to zero.  In fact, this is the default value for all
sprites after calling ia\_inituve.

A word of caution, however.  If you link a sprite to an image that has not
been loaded, the results will be unpredictable (okay, okay, it will most
likely crash the program).  So always, always make sure that the image the
sprite is linked to is loaded.  This might seem an easy thing to do, but
it gets a bit more complicated when you are dealing with more
sophisticated features such as chained sprites.  And with that, on to
chained sprites.

Related functions:
procedure ia\_displaysprite (n:integer;destofs,destseg:word);
procedure ia\_displaysprite\_mapped (n:integer;destofs,destseg:word;m:byte);
procedure ia\_displaysprite\_transparent
(n:integer;destofs,destseg:word;m:byte);

Sprite Chaining

In a real application, sprites rarely have a constant image throughout the
program.  Most likely, you will want the hero you are controlling to move
his legs when he is walking instead of sliding on the ground.  What this
means is that you will need to change the image that is linked to the
sprite.  This is easily done by setting n to a new number.  When dealing
with many sprites, however, this can become extremely difficult to keep
track of.  On top of that, some sprites loop through some predefined
frames of animation.  A fire, for example, can loop through five different
images to give the appearance of burning.  Can UVE32 help when it comes to
this kind of bookkeeping?  You bet.

Images are kept in an array called ln (the full description of the array
field is given at the end).  When you are loading a sprite in a slot, you
are simply giving the array index of that slot.  Each array item holds
pointers to the image data and collision detection information (stuff you
don't need to know about) along with the image's width, height (which are
handy to know about) and next field (which you do need to know about).
The next field is the number of another image slot.  Each frame, every
sprite that is linked to an image slot will be linked to the image slot
specified in the next field.  Take a moment to re-read the above sentence.
An example will make things clear (hopefully):

Assume that image slot number 7 has a next field with a value of 220.
This means that any sprite which is linked to image slot 7 (i.e.
spr[...].n:=7), after a frame occurs, will be linked to image slot 220
(i.e. spr[...].n:=220).  After yet another frame, sprites linked to image
slot 220 will be linked to the number of that slot's next field.  By
default, a slot's next field is initialized to the same slot number (i.e.
ln[x].next:=x).  This means that the sprite doesn't change it's image over
time.  You can change that, however.

The "chain" can be completely arbitrary, but what's usually chained are
images with consecutive slot numbers.  This is so because the
ia\_loadsprite function is capable of loading multi-image files into
consecutive slots.  Anyway, even if images are loaded one by one in
consecutive locations, they can easily be chained using:

ia\_chainsprite (start slot, chain length, end slot);

The start slot is the first slot in the chain.  The chain length is the
number of slots in the chain.  The end slot is what the next field of the
final chain slot will be set to.  To create an infinite loop, set end
slot=start slot.  To create a disappearing sprite, set end slot=0.  In my
games, I have frequently used missile smoke sprites.  These consist of a
few chained frames of a puff of smoke (decreasing in size), with the final
slot pointing to 0.  So, I can simply define a smoke sprite and let it
take its course, without worrying about when I should delete it.  It will
simply be deleted by itself when the time comes.  (Another, more general,
way is to set the life field of the spr array, as will be explained
further down the road.)

If you have created a chain, you can pick it up at any point.  For
example, if you have ten fires that you don't want to burn in sync with
one another, you can set their starting slots at different values within
the chain.  Check the examples for some, well, examples of this.

Related functions:
procedure ia\_chainsprite (nr,len,endloop:integer);
procedure ia\_unchainsprite (nr,len:integer);

Moving sprites

Sprites have coordinates, as specified by the x and y fields of spr.
Sprites move by changing these coordinates.  The coordinates are virtual
coordinates, in the integer range -32K to 32K in pixels.  If a sprite lies
outside the displayable area, it will not be displayed.  If it is
partially visible, it will be clipped.  Note that sprite visibility is not
a prerequisite for sprite collision.  Sprites can collide even outside the
visible area.

You can pan around the virtual world (i.e. change the visible area) by
setting vpx (viewport x) and vpy (viewport y) to appropriate values.  If
you have selected a scrolling background, it will scroll appropriately.
The viewport always spans (vpx,vpy)-(vpx+319,vpy+199).  (vpx,vpy) always
maps to the top left of the screen, even if an animation window has been
defined.

Related functions:
function ia\_visiblex(i:integer):boolean;
function ia\_visibley(i:integer):boolean;
function ia\_visible(i:integer):boolean;
procedure ia\_center(i,x,y:integer;pos:byte);

Sprite collision

Perhaps one of the most important aspects of sprites is the ability to
detect if two of them overlap ("collide").  After all, you wouldn't want
your missiles to whiz right through the enemy ships, would you?  In UVE32,
sprite collision is pixel-precise (with a few exceptions).  Bounding boxes
are not used, as they are very infuriating when dealing with 2D graphics
("But that missile didn't touch me!  I'm telling you it didn't touch
me!").  You are free to use the width and height variables to implement
such an algorithm, however.

To speed up collision detection, sprites are assumed to be vertically and
horizontally monotone, i.e. a vertical or horizontal line through the
sprite intersects its edges only twice.  Think of it as the sprite being
convex, only it includes and some cases of non-convex sprites.  Holes are
out of the question.  Another way of putting it is assuming that every
pixel between the leftmost and rightmost non-black pixels in each line
(and similarly topmost and bottommost for vertical lines) is considered to
be part of the sprite, and therefore can collide with another sprite.
This requires extra collision data to be stored along with the image data.
UVE32 takes care of that for you automatically.  All you need to remember
is to tick the "save collision data" box when saving sprites through the
utilities provided.

Sprite collision between two sprites can be detected by calling
ia\_collide, which will return true if the two sprite indices provided as
parameters overlap.  Caution!  You must make sure that both sprites have
collision data embedded in them.  UVE32 does not check for that, and will
use garbage data for collision, if none is available.

A couple of notes on sprite collision.  Sprites can collide in the 64Kx64K
virtual world, even outside the screen area.  A sprite cannot collide with
itself.  Inactive sprites cannot collide (sprites for which n:=0).
Another thing is that when there is obvious biasing towards sprite size in
collision pairs (as in the case of missile-spaceship, where the missile is
usually smaller than the ship), you will speed up collision check if you
pass the smallest sprite as the first parameter.

Related functions:
function ia\_collide(a,b:integer):boolean;

Deleting sprites & images

Images can be deleted but, in my experience, it's rarely necessary.
Should the need arise, you can call ia\_delspr to delete an image.  If you
load an image on top of a filled slot, the old image will be deleted and
memory will be freed before the new one is loaded.

Sprites are a different matter altogether.  They cannot be deleted in the
normal sense.  They are "deleted" by setting the n field to zero.  Another
way is to set the next field of some image slot to zero, as described in
the section about sprite chaining.  Yet another way is to use the life
field, which simply holds the number of frames left for which the sprite
will be visible.  Once this counter counts down to zero, the sprite is
deleted (i.e., not displayed).  When a sprite is not displayed, other
sprite fields remain unchanged, so if you want a sprite to blink, you can
toggle the n field between zero and some non-zero value.

Related functions:
procedure ia\_delspr (n:integer);

Other sprite attributes

For completeness, here is the whole sprite structure:

type  scb      =record
x,y,                        sprite coords
n,                     sprite loadnumber
life              :integer; frames left, if 0  n:=0
transparent  :boolean;      use sprite/background data
map               :byte;         which palette mapping to use
end;

Transparent specifies whether to use actual sprite data or the underlying
background data.  Why is that useful?  If map is zero, specifying that no
palette map will be used, then displaying the sprite will use the
background colors, in effect making it invisible.  That's of limited use
(although I've used it in a game).  If map is non-zero, however,
background colors will be mapped.  If the palette mapping used is, say,
one where each color maps to another of 70% brightness, then the net
effect will be a sprite that looks like a shadow.  Check the examples and
the palette maps section for more info.

And similarly, for the sprite images:

loaded         =record
data              :pointer;      pointer to sprite data
collength,                  length of collision data
length,                size in memory
width,height :word;       size of sprite
next              :word;         sprite sequence
end;
loadedarray         =array[0..nspr] of loaded;

Related Functions:
procedure ia\_setspritesused (i:integer);
procedure ia\_setclipdepth (i:integer);
procedure ia\_setwindow (x1,y1,x2,y2:integer);

Palettes

A palette is simply a set of 256 colors, each of which is comprised of
red, green, and blue values in the range 0-63.

palcolor       =record
red,green,blue:byte
end;
palette        =array[0..255] of palcolor;

You can define your own palettes, but UVE32 has two predefined palettes
called blackpal and pcxpal.  Blackpal is simply a palette where all the
colors have RGB triplets of (0,0,0) (i.e. they are all black).  Very handy
for those fade-ins/fade-outs.  Pcxpal is where the last loaded .PCX's
palette is stored.  Loading a .PCX file does not automatically set the
palette.

Finally, a note on setting the palette.  Continuously setting the palette
DAC (as happens in fade-ins/outs) can cause "snow" to appear on the
screen.  The effect can range from minimal to a complete snowstorm.  There
is no way around this, except inserting a delay between palette sets
and/or synchronizing to the VGA vertical retrace signal.  UVE32 protects
against these effects by synchronizing with the vertical retrace signal.
As all clones are not created equal, however, this does not guarantee that
it will work on your system.  If you experience snow, stay in until the
sun comes out :-)

Related functions:
procedure ia\_setpalette (pal:palette);
procedure ia\_getpalette(var pal:palette);
procedure ia\_loadpalette (filename:string; var p:palette);
procedure ia\_fadeto (s,t:palette; steps:word);
procedure ia\_weirdfadeto (s,t:palette;d:integer);

Palette maps

Palette maps are color look-up tables (CLUTs) that map each of the 256
colors to another color index.  They do not define new color values.
UVE32 defines maparray which holds 5 palette maps.

maparray       :array[1..5] of maptab;

These maps can be applied to sprites by setting the map field of the spr
structure to the color map index (1-5) of the palette map to use.  In such
a case, the sprite is not displayed in its normal colors, but goes through
a look-up stage.  Example time:  imagine that maparray[1] has all its
entries set to 255:

for i:=0 to 255 do maparray[1][i]:=255;

Then, if the map field of a sprite is set to 1, then every pixel of the
sprite will be displayed as color 255.  Again, the best way to understand
how these things work is to take a look at the examples.

Apart from defining a maparray entry manually, you can use
ia\_makeshadowmap and ia\_makeglenzmap, which set a map automatically.

Related functions:
function ia\_findclosestcolor (var p:palette; r,g,b:integer):byte;
procedure ia\_makeshadowmap (var p:palette; percent:integer;var
mapped:maptab);
procedure ia\_makeglenzmap (var p:palette; xr,xg,xb:integer;var
mapped:maptab);

Tiles

The background page holds a static image.  You can have a larger image
that you can pan around, however.  The memory required to store such an
image is prohibitive, so the image is composed of smaller 16x16 pixel
images called tiles. You can have as many as 255 tiles that make up an
image up to 5020 (stupid number, but don't ask) tiles in size (width x
height). Think of tiled floors or sidewalks and how a single tile can be
repeated to fill a larger area, only here you have a choice of 255 tiles
to place at each position.

In order to set up the scrolling background, you must first call
ia\_setscrolling.  This allocates memory for the tiles.  Your tile area can
have any dimension, as long as the total tiles do not exceed 5020.  You
set your desired tile area with ia\_setscrollarea.  Note that the width and
height parameters are given in tiles, not pixels.

You can scroll around the tiled imaged by changing the vpx and vpy
variables, which define the coordinates of the top-left of the screen into
your virtual world.

Tiles cannot have transparent areas.  If part of a tile is drawn in black,
then a black pixel will be placed on the screen.  The static background
will not show through.

If you pan out of the defined tile area, the screen is filled with the
tile at index 0.  In other words, the area outside of the tile area is
assumed to be filled with tile 0.

If your animation window is smaller than the screen, then the outside will
show the static background image.  If you intend to use the whole screen,
however, you can speed things up by not using the static background, since
no part of the background will be visible.  You can disable the static
background with the usebackground variable.

If you intend to use tiled backgrounds along with windowed animation, read
the bugs section for an important limitation.

Related functions:
procedure ia\_loadtil (filename:string; n:integer);
procedure ia\_displaytile (n:byte; lineofs,destseg:word);
procedure ia\_setscrolling;
procedure ia\_setscrollarea(x1,y1,w,h:integer);
procedure ia\_puttile(x,y:integer;n:byte);
function ia\_gettile(x,y:integer):byte;
procedure ia\_setstatic;

PCXs

UVE32 is capable of loading Zsoft's popular PCX file format pictures.  The
header is ignored, however, so PCX files must be exactly 320x200 in size,
with 256 colors.  Loading a PCX does not set its palette.  The palette is
automatically saved in the pcxpal variable.

Related functions:
procedure ia\_loadpcx (where:word;filename:string;seethru:byte);

Fonts

UVE32 uses BIOS mode 0x13, so there should be no problem displaying text
by calling standard procedures such as writeln.  Personally, I've never,
ever used the BIOS to print text.  Printing text in this way uses the
built-in (i.e., ugly) font.  On top of that, the background is destroyed.
Have no fear, though, because UVE32 is here to get you out of another
mess.  With its 15 fonts, horizontal and vertical printing, background
preservation, shadows, textures, proportional and fixed spacing, it's
everything the font-conscious user might want (okay, maybe not).

First thing's first, though.  In order to use fonts, some steps must be
taken.
ú    The file UVE.UVW must be in the current directory.
ú    You must load the font into memory by ia\_loadfont.  All of the 15
fonts can be present in memory at the same time.
ú    You must call ia\_setfontattr to set the desired font attributes.
ú    Finally, you can print text by calling ia\_printstr.

The 15 built-in fonts must be referred to by index number.  Okay, so an
enumeration would be a better idea, but no-one is stopping you from
creating one!  The fonts are:

Font index   Font name    Font origin
0            Default 5x5  InterAction
1            Default 5x5  InterAction
square
2            3x5          InterAction
3            3x5 square   InterAction
4            Future       Unknown
5            Antique      Unknown
6            Big          Unknown
7            Computer     Unknown
8            Deco         Unknown
9            Dott         Unknown
10           Medieval     Unknown
11           Modern       Unknown
12           Scrawl       Unknown
13           WC2          InterAction
14           5x5 Thick    InterAction

Take note of a few things when dealing with fonts.  First, make sure you
load the font before using it, otherwise you get a cryptic error message
about dereferencing a null pointer.  Second,  in the interest of speed, no
clipping is performed.  Third, the fire texture makes use of the palette
colors 224-245, so make sure you place your desired colors there (for
example, a red-yellow-white gradient). Fourth, whatever you do, never,
EVER try to .... oops, slipped my mind :-).

Related Functions:
procedure ia\_setfontattr (a:byte; b:fonttextures; c:fontcpi; d:fontorient;
e:byte; f:boolean; g:byte);
function ia\_strlength (s:string):word;
procedure ia\_printstr (where:word;xx,yy:integer; s:string; clr:byte);
procedure ia\_loadfont (i:byte);

FLIs

UVE32 is capable of loading and playing Autodesk .FLI files.  Before you
play any .FLI file you must make a call to ia\_setfliparameters to set some
parameters such as looping and play rate.   Apart from that, playing .FLI
files is as easy as calling ia\_playfli.  You can have more control over
the way a .FLI file is played by reverting to a lower-level interface.
Check the functions & procedures section for more info.

Related functions:
procedure ia\_openfli(filename:string);
procedure ia\_playframe;
procedure ia\_wait4nextframe;
procedure ia\_closefli;
procedure ia\_setfliparameters(a:integer;b:word;c:boolean);
procedure ia\_playfli(s:string);

WAD files

It is possible to combine all the read-only files (i.e., not files such as
config and highscore files, which are written to) that your application
needs in a single master wad file.  UVEDEMO uses such a file
(UVEDEMO.UVW).  UVW files are not fully supported in the shareware
version.  All the relevant code is there, but you need to register to be
able to create them.

Related functions:
procedure ia\_setwadfile (s:string);
function ia\_searchinwad (var fp:file;lookingfor:string):longint;

UVE Interface

Unit interface section

const     nspr      =500;               maximum number of sprites
maxtiles  =5020;              maximum number of scrolling area in
tiles

type   scb          =record
x,y,                        sprite coords
n,                     sprite loadnumber
life              :integer; frames left, if 0  n:=0
transparent  :boolean;      use sprite/background data
map               :byte;         which palette mapping to use
end;
scbarray  =array[0..nspr] of scb;
loaded         =record
data              :pointer; pointer to sprite data
collength,                  length of collision data
length,                size in memory
width,height :word;       size of sprite
next              :word;         sprite sequence
end;
loadedarray         =array[0..nspr] of loaded;
maptab              =array[0..255] of byte; used for colormapping
fontorient          =(horizontal,vertical); font attribute types
fontcpi        =(fixed,proportional);
fonttextures        =(plain,fire);
pagetype       =array[0..$FFFE] of byte;
pagepointer         =^pagetype;
palcolor       =record
red,green,blue:byte
end;
palette        =array[0..255] of palcolor;

var  vpx,vpy        :integer;      viewport topleft corner coords
hidden              :word;              segment of the hidden page
hiddenpoint         :pagepointer;  pointer to hidden page
background          :word;         segment of background
backgroundpoint     :pagepointer;       pointer to background
tiles               :word;              segment of tiles
tilespoint          :pagepointer;  pointer to tiles
pcxpal              :palette;      last PCXs palette
blackpal       :palette;      all blacks (0,0,0)
spritesloaded  :integer;      set by last "loadSPR" call
retraceenable,                wait 4 vertical retrace?
usebackground  :boolean;      copy bg to hidden page?
developermode  :boolean;      show developer stats
maparray       :array[1..5] of maptab;
       these tables are uses to map
       colors when display method
       is eg shadow, glenz, ...
spr            :scbarray;
ln             :loadedarray;
vga            :word;

lastframe      :boolean;
textenable          :boolean;      enables uve\_text
fliframenumber :word;              number of current FLI frame
frame               :integer;      current uve frame number

Other variables

ú    spritesloaded:  Sprites loaded by last ia\_loadspr call

ú    retraceenable (false):  If true, UVE waits for a vertical retrace
signal before copying the hidden page to the vga page.  This is not
needed, but included for the sake of completeness.  In the unlikely case
you are experiencing screen flicker, turn this option on.  Minimizes
flickering, but slows down frame rate.

ú    usebackground (true):   If true, UVE will copy the background page to
the hidden page before anything else to clear the last frame.   If you've
got a full-screen scrolling background, however, this is not necessary.
Turning this option off will improve frame rate.

ú    developermode (false):  When true, displays a bar on the top-left of
the screen with some statistics.  Each pixel in the graph corresponds to 1
millisecond:
ú    White portion represents time spend by UVE rendering the screen.
ú    Blue portion represents time taken by your program apart from
rendering time.  This includes game logic time, collision checks, keyboard
input etc.
ú    Red portion represents time taken to copy hidden to vga page.  The
reason this is separate is that, depending on your VGA, it can take up to
90% of the total frame time.
ú    White arrow under bar represents desired (set) frame rate.
Note that colors mentioned correspond to default palette.

ú    lastframe (false):  True if current FLI frame is the last frame.
Used for manual FLI play loops.
ú    textenable (true):  Set to false if you don't want any text output
from UVE (for example when loading sprites).  Output is always disabled
when in graphics mode.
ú    fliframenumber (0):  Current FLI frame number
ú    frame (0):  Current UVE frame number

Functions & Procedures

The functions and procedures of UVE are divided into four categories:
general-purpose, beginner, intermediate and advanced.  General purpose
procedures are simple "utility" procedures.  Beginner entries include all
procedures that you must absolutely know about in order to use UVE.
Intermediate entries refer to commands that you will use frequently when
you've learned the ropes.  Advanced entries, finally, provide a lower
lever interface to UVE and, as such, are more powerful and allow for
extensive customization.  You do not have to know any of the advanced
commands, but they do come in handy in certain situations.

General Purpose Commands

function i2s (i:integer):string;
Purpose        Convert an integer to its string representation
Parameters     i    Integer variable to be converted
Return         String representation of i
Notes          -
See also       l2s, w2s

function w2s (w:word):string;
Purpose        Convert a word to its string representation
Parameters     w    Word variable to be converted
Return         String representation of w
Notes          i2s, l2s
See also       -

function l2s (l:longint):string;
Purpose        Convert an long integer to its string representation
Parameters     l    Longint variable to be converted
Return         String representation of l
Notes          -
See also       i2s, w2s

function max (a,b:integer):integer;
Purpose        Return greater of two numbers
Parameters     a,b  Integers to be compared
Return         Greatest integer
Notes          -
See also       min

function min (a,b:integer):integer;
Purpose        Return smaller of two numbers
Parameters     a,b  Integers to be compared
Return         Smallest integer
Notes          -
See also       max

procedure ia\_checkfile (s:string);
Purpose        Check whether a file exists
Parameters     s    Filename
Return         -
Notes          Calls ia\_error if file does not exist
See also       -

procedure ia\_checkmem (w:word);
Purpose        Check for available memory
Parameters     w    Requested memory in bytes
Return         -
Notes          Calls ia\_error if free memory is less than w
See also       -

Beginner Commands

procedure ia\_loadtil (filename:string; n:integer);
Purpose        Load a tile
Parameters     filename  UVT or UVL file name
n    Index of tile
Return         -
Notes          Calls ia\_error if file is not found
See also       ia\_setscrolling, ia\_puttile, ia\_gettile, ia\_displaytile

procedure ia\_loadspr (filename:string; n:integer);
Purpose        Load a sprite
Parameters     filename  UVS or UVL file name
n    Index of sprite
Return         -
Notes          Calls ia\_error if file is not found
Sets spritesloaded to the number of sprites loaded
See also       ia\_delspr

procedure ia\_loadpcx (where:word; filename:string; seethru:byte);
Purpose        Load a PCX file
Parameters     where     Page segment
filename  PCX file name
seethru   Transparent color (255=none)
Return         -
Notes          PCX palette is stored in pcxpal
See also       -

procedure ia\_setpalette (pal:palette);
Purpose        Set the current palette
Parameters     pal  Palette to set
Return         -
Notes          -
See also       ia\_loadpalette, ia\_getpalette

procedure ia\_loadpalette (filename:string; var p:palette);
Purpose        Load a palette
Parameters     filename  PAL file name
p    Palette variable to store result into
Return         -
Notes          -
See also       ia\_setpalette, ia\_getpalette

procedure ia\_setscrolling;
Purpose        Set scrolling (tiled) background
Parameters     -
Return         -
Notes          Allocates tiles page first time it's called
See also       ia\_setstatic

procedure ia\_setscrollarea (x1,y1,w,h:integer);
Purpose        Set scrolling area
Parameters     x1,y1     Coordinates of top-left corner in pixels
w,h  Width and height of scroll area in tiles
Return         -
Notes          x1,y1 are automatically aligned on a 16x16 grid
See also       ia\_setscrolling

procedure ia\_puttile (x,y:integer; n:byte);
Purpose        Set a tile on the scroll area
Parameters     x,y  Coordinates to place tile in pixels
n    Tile number
Return         -
Notes          x1,y1 are automatically aligned on a 16x16 grid
See also       ia\_gettile

procedure ia\_setfontattr (a:byte; b:fonttextures; c:fontcpi; d:fontorient;
e:byte; f:boolean; g:byte);
Purpose        Set font attribute
Parameters     a    Font number
b    Font texture.  Can be plain or fire
c    Character spacing.  Can be fixed or proportional
d    Font orienation.  Can be horizontal or vertical
e    Background color.  Use 255 for transparent background
f    True for a font shadow to be displayed
g    Shadow color
Return         -
Notes          Fire uses color indices 224-245
Font must be loaded first
See also       ia\_loadfont, ia\_strlength, ia\_printstr

procedure ia\_printstr (where:word; xx,yy:integer, s:string; clr:byte);
Purpose        Print a string
Parameters     where     Page segment
xx,yy     Coordinates where string printing will start in pixels
s    String to print
clr  String color
Return         -
Notes          Use xx=-32768 to center the string on screen
No clipping is performed
See also       ia\_loadfont, ia\_setfontattr, ia\_strlength

procedure ia\_loadfont (i:byte);
Purpose        Load a font
Parameters     i    Font number
Return         -
Notes          Calls ia\_error if UVE.UVW is not present in the current
directory
See also       ia\_setfontattr, ia\_strlength, ia\_printstr

procedure ia\_powerup;
Purpose        Switch to graphics mode 0x13
Parameters     -
Return         -
Notes          -
See also       ia\_shutdown

procedure ia\_shutdown;
Purpose        Switch to text mode 0x03
Parameters     -
Return         -
Notes          -
See also       ia\_powerup

procedure ia\_playfli (s:string);
Purpose        Play a FLI file
Parameters     s    FLI file name
Return         -
Notes          Calls ia\_error if file cannot be found
See also       ia\_setfliparameters, ia\_openfli, ia\_playframe,
ia\_wait4nextframe, ia\_closefli

procedure ia\_inituve;
Purpose        Initialize UVE32
Parameters     -
Return         -
Notes          Call before anything else.
Call once only.
See also       -

procedure ia\_doframe;
Purpose        Execute frame
Parameters     -
Return         -
Notes          Calls parts 1,2 and 3
See also       ia\_doframepart1, ia\_doframepart2, ia\_doframepart3

Intermediate Commands

procedure ia\_getpalette (var pal:palette);
Purpose        Get the current palette
Parameters     pal  Palette variable to store result into
Return         -
Notes          -
See also       ia\_loadpalette, ia\_setpalette

procedure ia\_setwadfile (s:string);
Purpose        Set the current UVW file
Parameters     s    Filename
Return         -
Notes          When s is specified, all PCX/UVS/UVL/FLI/UVT files will be
loaded from s
To load files normally, call ia\_setwadfile(*);
        Calls ia\_error if file does not exist
See also       ia\_searchinwad*

procedure ia\_copypage (source,dest:word);
Purpose        Copy a page
Parameters     source    Source page segment
target    Target page segment
Return         -
Notes          -
See also       -

procedure ia\_cls (where:word; col:byte);
Purpose        Clear a page
Parameters     where     Page segment
col  Color to use
Return         -
Notes          -
See also       -

procedure ia\_putpixel (where,x,y:word; c:byte);
Purpose        Plot a pixel
Parameters     where     Page segment
x,y  Point coordinates
c    Color to use
Return         -
Notes          No clipping is performed
See also       ia\_getpixel

function ia\_getpixel (where,x,y:word):byte;
Purpose        Read a pixel
Parameters     where     Page segment
x,y  Point coordinates
Return         Color of specified pixel
Notes          No clipping is performed
See also       ia\_putpixel

procedure ia\_hline (where:word; x,y,len:integer; c:byte);
Purpose        Draw a horizontal line
Parameters     where     Page segment
x,y  Starting point coordinates
len  Line length in pixels
Return         -
Notes          Performs no clipping
See also       ia\_vline, ia\_line

procedure ia\_vline (where:word; x,y,len:integer; c:byte);
Purpose        Draw a vertical line
Parameters     where     Page segment
x,y  Starting point coordinates
len  Line height in pixels
Return         -
Notes          Performs no clipping
See also       ia\_hline, ia\_line

procedure ia\_line (where:word; x1,y1,x2,y2:integer; color:byte);
Purpose        Draw a line using Bresenham's algorithm
Parameters     where     Page segment
x1,y1     Start point coordinates
x2,y2     End point coordinates
color     Color to use
Return         -
Notes          Performs no clipping
See also       ia\_vline, ia\_hline

procedure ia\_box (where:word; x1,y1,x2,y2:integer; c:byte;
filled:boolean);
Purpose        Draw a box
Parameters     where     Page segment
x1,y1     Start point coordinates
x2,y2     End point coordinates
c    Color to use
filled    If true, box is filled with color c
If false, only a hollow rectangle is drawn
Return         -
Notes          Performs no clipping
See also       ia\_box\_clip

procedure ia\_box\_clip (where:word; x1,y1,x2,y2:integer; c:byte;
filled:boolean);
Purpose        Draw a box
Parameters     where     Page segment
x1,y1     Start point coordinates
x2,y2     End point coordinates
c    Color to use
filled    If true, box is filled with color c
If false, only a hollow rectangle is drawn
Return         -
Notes          Same as ia\_box, but performs clipping as well
See also       ia\_box

procedure ia\_fadein (where,time:word);
Purpose        Dissolve a page onto the VGA page
Parameters     where     Page to be dissolved
time Speed of transition
Return         -
Notes          Very slow on some 386s
See also       -

procedure ia\_makeshadowmap (var p:palette; percent:integer; var
mapped:maptab);
Purpose        Make a shadow map
Parameters     p    Palette variable to use as a base for mapping
percent   Shadow percentage
mapped    Map table variable to store result into
Return         -
Notes          Percent can be more than 100, which will result in a
brighter colormap
See also       ia\_findclosestcolor, ia\_makeglenzmap

procedure ia\_makeglenzmap (var p:palette; xr,xg,xb:integer; var
mapped:maptab);
Purpose        Make a glenz (translucency) map
Parameters     p    Palette variable to use as a base for mapping
xr,xg,xb  RGB components to add to each color
mapped    Map table variable to store result into
Return         -
Notes          xr,xg,xb can be positive or negative
See also       ia\_findclosestcolor, ia\_makeshadowmap

procedure ia\_fadeto (s,t:palette; steps:word);
Purpose        Cross-fade between two palettes using linear interpolation
Parameters     s    Source palette
t    Target palette
steps     Cross-fade duration
Return         -
Notes          -
See also       ia\_weirdfadeto, ia\_loadpalette, ia\_setpalette,
ia\_getpalette

procedure ia\_weirdfadeto (s,t:palette; d:integer);
Purpose        Cross-fade between two palettes using integer RGB matching
Parameters     s    Source palette
t    Target palette
steps     Cross-fade duration
Return         -
Notes          Faster than ia\_fadeto but may result in slight hue shifts
while cross-fading
See also       ia\_fadeto, ia\_loadpalette, ia\_setpalette, ia\_getpalette

function ia\_visible (i:integer):boolean;
Purpose        Test for sprite visibility in both axes
Parameters     i    Sprite number
Return         True if sprite is visible on screen
Notes          Uses bounding box, not actual sprite geometry
See also       ia\_visiblex, ia\_visibley

procedure ia\_center (i,x,y:integer; pos:byte);
Purpose        Center a sprite around a point
Parameters     i    Sprite number
x,y  Coordinates of center point
pos  Centering method:
2    (x,y) becomes mid-bottom of sprite
4    (x,y) becomes mid-left of sprite
5    (x,y) becomes center of sprite
6    (x,y) becomes mid-right of sprite
8    (x,y) becomes mid-top of sprite
Return         -
Notes          Hint for centering method: Look at the numeric keypad.
Sprite boundary is
123/456/789 "box".  Centering method corresponds to number on
each key.
See also       -

function ia\_collide (a,b:integer):boolean;
Purpose        Test for sprite collision
Parameters     a,b  Sprite numbers
Return         True if there is a collision between sprites a and b
Notes          Collision can be off-screen
Both sprites must have collision data embedded in their format!
See also       -

procedure ia\_chainsprite (nr,len,endloop:integer);
Purpose        Chain sprites together
Parameters     nr   Start sprite number for chain
len  Length of chain
endloop   Final chain sprite link
Return         -
Notes          Sprite will cycle nr nr+1  nr+2  ...  nr+len  endloop
Infinite loops can be created by setting endloop=nr
See also       ia\_unchainsprite

procedure ia\_unchainsprite (nr,len:integer);
Purpose        Unchain previously chained sprites
Parameters     nr   Start sprite number for chain
len  Unchain length
Return         -
Notes          -
See also       ia\_chainsprite

function ia\_gettile (x,y:integer):byte;
Purpose        Get a tile from the scroll area
Parameters     x,y  Coordinates to get tile from in pixels
Return         Tile number under x,y
Notes          x1,y1 are automatically aligned on a 16x16 grid
See also       ia\_puttile

procedure ia\_setstatic;
Purpose        Set static background (disable scrolling background)
Parameters     -
Return         -
Notes          Tiles page is not deallocated
See also       ia\_setscrolling

procedure ia\_setcycletime (i:integer);
Purpose        Set frame duration
Parameters     i    Frame duration in milliseconds
Return         -
Notes          Frame rate will be limited to i.
Has no effect if frames cannot be displayed as fast as i
See also       -

procedure ia\_setwindow (x1,y1,x2,y2:integer);
Purpose        Set animation window
Parameters     x1,y1     Coordinates of top-left corner of animation
window
x2,y2     Coordinates of bottom-right corner of animation window
Return         -
Notes          -
See also       -

Advanced Commands

function clock:longint;
Purpose        Return the current time
Parameters     -
Return         Milliseconds elapsed since midnight
Notes          -
See also       -

procedure ia\_error (caller:string; errornum:byte; param:string);
Purpose        Error handling routine
Parameters     caller    Procedure that generated the error
errornum Error number
param     Parameter that caused the error
Return         -
Notes          Program halts after printing error.
Possible error numbers are.
1    Parameter(s) out of range.
2    File does not exist.
3    Not an UVE file.
4    Wrong file type.
5    Not enough memory.
6    Attempt to dereference nil pointer.
7    No VGA display adapter detected.
8    Scrolling area too large.
9    Tile placed out of scroll area.
See also       -

function ia\_detectvga:boolean;
Purpose        Detect the presence of a VGA adapter
Parameters     -
Return         True if VGA present
Notes          -
See also       -

procedure ia\_drawasciiscreen;
Purpose        Draw UVE opening text screen
Parameters     -
Return         -
Notes          -
See also       ia\_uvetext

procedure ia\_uvetext (caller, strng, parameter: string);
Purpose        Print out text in UVE standardized format
Parameters     caller    Calling procedure
parameter Text to print
Return         -
Notes          -
See also       ia\_drawasciiscreen

procedure ia\_waitretrace;
Purpose        Wait for VGA vertical retrace signal
Parameters     -
Return         -
Notes          Not needed, but included for completeness
See also       -

procedure ia\_delspr (n:integer);
Purpose        Delete a sprite from memory
Parameters     n    Sprite number to delete
Return         -
Notes          -
See also       ia\_loadspr

function ia\_searchinwad (var fp:file; lookingfor:string):longint;
Purpose        Position a file pointer to a specified entry in a UVW file
Parameters     fp   File handle (must be of type FILE)
Return         Size of file requested
Notes          Calls ia\_error if entry is not present in UVW
See also       ia\_setwadfile

function ia\_findclosestcolor (var p:palette; r,g,b:integer):byte;
Purpose        Find closest color using least squares method
Parameters     p    Palette var to search in
r,g,b     Desired RGB components
Return         Index of closest color matching RGB components specified
Notes          -
See also       ia\_makeshadowmap, ia\_makeglenzmap

function ia\_visiblex (i:integer):boolean;
Purpose        Test for sprite visibility in x-axis
Parameters     i    Sprite number
Return         True if sprite is visible on screen x-extents
Notes          Uses bounding box, not actual sprite geometry
See also       ia\_visibley, ia\_visible

function ia\_visibley (i:integer):boolean;
Purpose        Test for sprite visibility in y-axis
Parameters     i    Sprite number
Return         True if sprite is visible on screen y-extents
Notes          Uses bounding box, not actual sprite geometry
See also       ia\_visiblex, ia\_visible

procedure ia\_displaysprite (n:integer; destofs,destseg:word);
Purpose        Display a sprite
Parameters     n    Sprite number
destofs   Destination offset
destseg   Destination segment
Return         -
Notes          Performs no clipping
See also       ia\_displaysprite\_mapped, ia\_displaysprite\_transparent

procedure ia\_displaysprite\_mapped (n:integer; destofs,destseg:word;
m:byte);
Purpose        Display a sprite using a map table
Parameters     n    Sprite number
destofs   Destination offset
destseg   Destination segment
m    Map table index
Return         -
Notes          Performs no clipping
See also       ia\_displaysprite, ia\_displaysprite\_transparent

procedure ia\_displaysprite\_transparent (n:integer; destofs,destseg:word;
m:byte);
Purpose        Display a transparent sprite using a map table
Parameters     n    Sprite number
destofs   Destination offset
destseg   Destination segment
m    Map table index
Return         -
Notes          Performs no clipping
See also       ia\_displaysprite, ia\_displaysprite\_mapped

procedure ia\_displaytile (n:byte; lineofs,destseg:word);
Purpose        Display a tile
Parameters     n    Tile number
lineofs   Destination offset
destseg   Destination segment
Return         -
Notes          Performs no clipping
See also       ia\_loadtil, ia\_gettile, ia\_puttile

procedure ia\_doframepart1;
Purpose        Execute first part of frame cycle
Parameters     -
Return         -
Notes          Copies background page onto hidden page and/or constructs
tiled background
See also       ia\_doframepart2, ia\_doframepart3, ia\_doframe

procedure ia\_doframepart2;
Purpose        Execute second part of frame cycle
Parameters     -
Return         -
Notes          Display all sprites onto hidden page
See also       ia\_doframepart1, ia\_doframepart3, ia\_doframe

procedure ia\_doframepart3;
Purpose        Execute third part of frame cycle
Parameters     -
Return         -
Notes          Copy  hidden page to vga page
See also       ia\_doframepart1, ia\_doframepart2, ia\_doframe

procedure ia\_setspritesused (i:integer);
Purpose        Set number of active sprites
Parameters     i    Sprite number
Return         -
Notes          Only sprites with number between 1 and i will be displayed
See also       -

procedure ia\_setclipdepth (i:integer);
Purpose        Set number of sprites clipped to screen ("in front" of
animation window)
Parameters     i    Sprite number
Return         -
Notes          Sprites with number between 1 and i will be clipped to
320x200 screen
Sprites with number between i+1 and nmax will be clipped to
animation window
See also       -

function ia\_strlength (s:string):word;
Purpose        Get string length
Parameters     s    String to calculate length of
Return         Length of string in pixels when printed out in the current
font attributes
Notes          -
See also       ia\_loadfont, ia\_setfontattr, ia\_printstr

procedure ia\_newpage (var p:pagepointer; var where:word);
Purpose        Allocate a new page
Parameters     -
Return         p    points to the new allocated page
where     holds new page segment
Notes          Calls ia\_error if there is not enough memory left
See also       -

procedure ia\_openfli (filename:string);
Purpose        Open a FLI file
Parameters     filename  FLI file name
Return         -
Notes          Calls ia\_error if file is cannot be found
See also       ia\_setfliparameters, ia\_playframe, ia\_wait4nextframe,
ia\_closefli, ia\_playfli

procedure ia\_playframe;
Purpose        Play the next frame of a FLI file
Parameters     -
Return         -
Notes          -
See also       ia\_setfliparameters, ia\_openfli, ia\_wait4nextframe,
ia\_closefli, ia\_playfli

procedure ia\_wait4nextframe;
Purpose        Wait until current FLI frame time expires
Parameters     -
Return         -
Notes          -
See also       ia\_setfliparameters, ia\_openfli, ia\_playframe, ia\_closefli,
ia\_playfli

procedure ia\_closefli;
Purpose        Close a FLI file
Parameters     -
Return         -
Notes          -
See also       ia\_setfliparameters, ia\_openfli, ia\_playframe,
ia\_wait4nextframe, ia\_playfli

procedure ia\_setfliparameters (a:integer; b:word; c:boolean);
Purpose        Set FLI play parameters
Parameters     a    FLI playing speed
b    FLI loop times
c    True if FLI can be interrupted by a keypress
Return         -
Notes          Use a=-1 to use FLI internal speed
See also       ia\_openfli, ia\_playframe, ia\_wait4nextframe, ia\_closefli,
ia\_playfli

Supporting Utilities

UVSINFO

UVSINFO is a simple utility that gives information about sprites contained
in a single/multiple sprite file (.UVS/.UVL).

PCX2UVS

PCX2UVS is a utility that converts a PCX file into a sprite (.UVS) file.
It can also optionally save the PCX's palette for use with that sprite.
The PCX's background must be black (color index 0).  UVE32 automatically
calculates the bounding box from the PCX image and saves the sprite.  Any
part of the sprite that is drawn in black will be completely transparent
when displayed on the screen.  A PCX file can only hold a single sprite.
(You can get a far more powerful version of PCX2UVS if you register).

PCX2UVT

PCX2UVT is a utility that converts a PCX file into a tile (.UVT) file.
The PCX's background must be black (color index 0).  No bounding box is
used.  The first non-black pixel found is assumed to be the top-left pixel
of a 16x16 tile.  You can have multiple tiles in the PCX.  In such a case,
the tiles will all be saved in a single file in the order they were
detected (top-to-bottom, left-to-right).

Note:  As no bounding box is used when saving tiles, the top-left pixel of
each tile must not be black, so that the start of a tile is properly
detected.

LIBMAKER

LIBMAKER is a powerful utility that allows you to combine multiple files
together.  Its most obvious use is to concatenate .UVS or .UVT files into
library (.UVL) files.  It cannot be used to create wad files (.UVW).  The
files will be concatenated in the order they were selected.

There is a maximum of 100 files that can be simultaneously displayed.
This means that your UVL files can contain at most 100 sprites/tiles.
Workaround:  First split your files into groups of (at most) 100 files,
combine them separately, and then combine the resultant UVL files into
your final master UVL file.  Hope you got that.

Known bugs... err.. features

The following list contains all the bugs/limitations I am aware of (but
don't intend to fix, at least in the near future).

ú    When using a scrolling (tiled) background, the animation window must
be at least 16 pixels long in both dimensions, i.e. it must be able to
contain at least one full tile.  Tiles are not clipped properly if the
animation window is smaller than that.

UVE32 Frequently Asked Questions

ú    Why is there still only one question in the UVE32 FAQ?
What can I say?  There haven't been any frequently asked questions.
This can only mean two things: Either UVE32 is flawless, or nobody
has bothered downloading it :-)

UVE mailing list

Starting with v1.40 there is a mailing list which you can join.   You  can
use  the mailing list to communicate with other UVE users world-wide, post
problems, comments, suggestions and so on.  To join the mailing list  send
e-mail to:

majordomo@lennon.shim.org.sg

with the words "subscribe uve" in the body of the message (subject is  not
important).   You  should get a confimation back upon  joining  the  list,
along with some additional information.

Where can I get UVE32?

The two primary sites where the lastest version of UVE32 will be uploaded
first are:

ú    The SimTel archive in the US (ftp to ftp.simtel.net or ftp.cdrom.com)
in pub/simtelnet/msdos/turbopas/
ú    The X2 archive in Finland (ftp to x2ftp.oulu.fi) in
pub/msdos/programming/libs/

Of course, since everybody mirrors everybody else these days, it should
soon spread to just about everywhere.  If you cannot access these sites,
try getting UVE32 from a nearby mirror site.  At the time of this writing,
Country   Host           Directory
Argentina           ftp.satlink.com               /pub/mirrors/simtelnet
Australia           ftp.bhp.com.au                /pub/simtelnet
Australia           ftp.iniaccess.net.au          /pub/simtelnet
Australia           ftp.tas.gov.au                /pub/simtelnet
Australia           sunsite.anu.edu.au            /pub/pc/simtelnet
Austria             ftp.univie.ac.at              /mirror/simtelnet
Belgium             ftp.linkline.be               /mirror/simtelnet
Belgium             ftp.tornado.be                /pub/simtelnet
Bulgaria            ftp.eunet.bg                  /pub/simtelnet
Brazil              ftp.iis.com.br                /pub/simtelnet
Brazil              ftp.unicamp.br                /pub/simtelnet
Canada,Ottawa       ftp.crc.doc.ca                /systems/ibmpc/simtelnet
Canada,Vancvr  ftp.direct.ca                 /pub/simtelnet
Chile               sunsite.dcc.uchile.cl         /pub/Mirror/simtelnet
China               ftp.pku.edu.cn                /pub/simtelnet
Czech Republic      ftp.eunet.cz                  /pub/simtelnet
Czech Republic      pub.vse.cz                    /pub/simtelnet
Czech Republic      ftp.zcu.cz                    /pub/simtelnet
Finland             ftp.funet.fi
/mirrors/ftp.simtel.net/pub/simtelnet
France              ftp.grolier.fr                /pub/simtelnet
France              ftp.ibp.fr                    /pub/simtelnet
Germany             ftp.mpi-sb.mpg.de             /pub/simtelnet
Germany             ftp.rz.ruhr-uni-bochum.de     /pub/simtelnet
Germany             ftp.tu-chemnitz.de            /pub/simtelnet
Germany             ftp.uni-heidelberg.de         /pub/simtelnet
Germany             ftp.uni-magdeburg.de          /pub/mirrors/simtelnet
Germany             ftp.uni-paderborn.de          /pub/simtelnet
Germany             ftp.uni-trier.de
/pub/pc/mirrors/simtelnet
Germany             ftp.rz.uni-wuerzburg.de       /pub/pc/simtelnet
Greece              ftp.ntua.gr                   /pub/pc/simtelnet
Hong Kong           ftp.cs.cuhk.hk                /pub/simtelnet
Hong Kong           ftp.hkstar.com                /pub/simtelnet
Hong Kong           sunsite.ust.hk                /pub/simtelnet
Israel              ftp.huji.ac.il                /pub/simtelnet
Italy               cis.utovrm.it                 /simtelnet
Italy               ftp.flashnet.it               /pub/simtelnet
Italy               ftp.unina.it                  /pub/simtelnet
Italy               mcftp.mclink.it               /pub/simtelnet
Japan               ftp.iij.ad.jp                 /pub/simtelnet
Japan               ftp.riken.go.jp               /pub/simtelnet
Japan               ftp.saitama-u.ac.jp           /pub/simtelnet
Japan               ftp.u-aizu.ac.jp              /pub/PC/simtelnet
Japan               ring.aist.go.jp               /pub/simtelnet
Japan               ring.asahi-net.or.jp          /pub/simtelnet
Latvia              ftp.lanet.lv                  /pub/mirror/simtelnet
Malaysia            ftp.jaring.my                 /pub/simtelnet
Malaysia            ftp.mimos.my                  /pub/simtelnet
Mexico              ftp.gdl.iteso.mx              /pub/simtelnet
Netherlands         ftp.euro.net                  /d5/simtelnet
Netherlands         ftp.nic.surfnet.nl            /mirror-
archive/software/simtelnet
New Zealand         ftp.vuw.ac.nz                 /pub/simtelnet
Norway              ftp.bitcon.no                 /pub/simtelnet
Poland              ftp.cyf-kr.edu.pl             /pub/mirror/Simtel.Net
Poland              ftp.icm.edu.pl                /pub/simtelnet
Poland              ftp.man.poznan.pl             /pub/simtelnet
Portugal             ftp.ip.pt                    /pub/simtelnet
Portugal            ftp.ua.pt                     /pub/simtelnet
Romania             ftp.sorostm.ro                /pub/simtelnet
Singapore           ftp.nus.sg                    /pub/simtelnet
Slovakia            ftp.uakom.sk                  /pub/simtelnet
Slovenia            ftp.arnes.si                  /software/simtelnet
South Africa        ftp.is.co.za                  /pub/simtelnet
South Africa        ftp.sun.ac.za                 /pub/simtelnet
South Korea         ftp.nuri.net                  /pub/simtelnet
South Korea         ftp.sogang.ac.kr              /pub/simtelnet
South Korea         sunsite.snu.ac.kr             /pub/simtelnet
Spain               ftp.rediris.es                /mirror/simtelnet
Sweden              ftp.sunet.se                  /pub/simtelnet
Switzerland         ftp.switch.ch                 /mirror/simtelnet
Taiwan              ftp.ncu.edu.tw                /Packages/simtelnet
Taiwan              nctuccca.edu.tw               /mirror/simtelnet
Thailand            ftp.nectec.or.th              /pub/mirrors/simtelnet
UK, Edinburgh       emwac.ed.ac.uk                /mirrors/simtelnet
UK, London          ftp.demon.co.uk               /pub/simtelnet
UK, Lancaster       micros.hensa.ac.uk            /pub/simtelnet
UK, London          sunsite.doc.ic.ac.uk          /packages/simtelnet
US, California      ftp.cdrom.com                 /pub/simtelnet
US, California      ftp.digital.com               /pub/micro/pc/simtelnet
US, Illinois        uiarchive.cso.uiuc.edu
/pub/systems/pc/simtelnet
US, Mass.           ftp.bu.edu                    /pub/mirrors/simtelnet
US, Michigan        oak.oakland.edu               /pub/simtelnet
US, New York        ftp.rge.com                   /pub/systems/simtelnet
US, Oklahoma        ftp.ou.edu                    /pub/simtelnet
US, Oregon          ftp.orst.edu                  /pub/simtelnet
US, Utah            ftp.cyber-naut.com            /pub/simtelnet
US, Virginia        mirrors.aol.com               /pub/simtelnet

For the X2 archive:

Site: ftp.ibp.fr (France)
Path: /pub/pc/x2ftp/
Mirror: books,msdos
Update: 0330 GMT

Site: ftp.rz.uni-karlsruhe.de (Germany)
Path: /pub/programming/mirror.x2ftp/
Mirror: books,msdos,unix
Update: 0200 GMT

Site: ftp.infomagic.com (USA)
Path: /pub/mirrors/x2ftp/
Mirror: amiga,books,console,msdos,standards
Update: 0400 GMT

Site: illusion.shiny.it (Italy)
Path: /pub/x2ftp/
Mirror: msdos
Update: 0500 GMT

Site: mirrors.aol.com (USA)
Path: /pub/x2ftp
Mirror: books,console,msdos
Update: 2330 GMT

Site: ftp.ee.techpta.ac.za (168.172.8.5) (South Africa)
Path: /pub/mirrors/x2ftp/
Mirror:
Update: 2300 GMT

Site: ftp.lanet.lv (Latvia)
Path: /pub/mirror/x2ftp/
Mirror: books,msdos
Update: 0130 GMT

Site: http://www2.cp.eng.chula.ac.th/mirror1/x2ftp
Mirror: msdos
Update: 2100 GMT
Freq.: weekly (Friday)
Admin: ftpadm@cpu.cp.eng.chula.ac.th

Contacting InterAction software

You can contact me for any reason, whether it's to ask for registration
information, to ask if/how you can do something in UVE32, to report a bug,
or just to say what you like/don't like about UVE32.  Alternatively, you
can join the UVE mailing list (more information in the relevant section).

When writing in to report a bug or ask something about a command, please
take the time to read through the manual.  There is a good chance the
answer you are looking for is already there.  Also, check the FAQ for
answers to frequently asked questions.  When you writing in with a
question, please include in your mail information about the version of
UVE32 you are using.

Okay, by far the best way to contact me is through e-mail.  My address is:

 cbp@doc.ic.ac.uk

Note that this address is only valid until the 1st of July, 1998.
Furthermore, avoid sending mail to that address during the Christmas,
Easter, and Summer holidays as I will not be checking my mail regularly
during those times.  You can alternatively send mail to the following
address:

   robin@hol.net

It's probably A Good Idea to send your mail to both addresses to minimize
latency time (I love it when I use jargon).  Some e-mail bounces, so if
you haven't heard from me in 15 days, send your mail again, perhaps
including more complete or alternative reply addresses.

If you have no access to the Internet, You can use conventional surface
mail, although I can't guarantee how long it's going to take before you
get an answer.  You can write to:

Constantine Prouskas
4 Adrianoupoleos street
 GR 156-69 Papagou
  Athens, GREECE

Registering

UVE32 is shareware.  It is not free.  If you use UVE32 for 21 days and
wish to continue using it, you must register it.  Read the License
Agreement for more information on what you are and are not allowed to do.
By registering you are acknowledging all he work that has gone behind this
product and supporting further development.

By registering, you get:

ú    My eternal gratitude :-)
ú    The latest version of UVE32 for Turbo Pascal 6.0 & 7.0, plus the
protected mode version for Borland Pascal 7.0.
ú    Unlimited mail/e-mail support (including hot tips on how it's
possible to have a 2-player split screen in UVE32).
ú    The complete documentation in Rich Text Format (.RTF), complete with
advanced formatting and tables.
ú    Registered versions of all the supporting utilities, including
UVSINFO, PCX2UVS, PCX2UVT, LIBMAKER.
ú    An advanced, powerful version of PCX2UVS that allows multiple sprites
per PCX and complete control over the save region.
ú    WADMAKER:  An extra utility that can create .UVW files.
ú    WADVIEW:  An extra utility that shows the contents of .UVW files.
ú    FLI2UVL:  An extra utility that directly creates a UVL file from a
FLI file.
ú    \*NEW!\* UVE\_KEY: A unit to handle multiple keypresses.  An absolute
must for games.

Registration is US$25.  There is a 20% discount to any cheque or cash
orders (amount after discount = US$20).

Starting with v1.40, it is now possible to register using your credit
card.  Since this has made things a bit more complicated, I have split up
the registration to credit card and non-credit card orders.

Credit card orders

For your convenience, I have contacted another company, NorthStar
solutions, to process any orders you may wish to place with your Visa,
MasterCard or Discover card.  NorthStar Solutions can be easily contacted
for orders only via any of the following methods:

ú    PHONE ORDERS
Available 10am-8pm, EST, Monday through Saturday
1-800-699-6395 (Calls from the U.S. only.)
1-803-699-6395 (Calls from outside the U.S.)

ú    FAX ORDERS
1-803-699-5465 (Available 24 hours.  International and business orders
encouraged.)

ú    INTERNET ORDERS
Simply fill out the online order form at
http://ourworld.compuserve.com/homepages/starmail

ú    E-MAIL ORDERS
You can send your order via e-mail to:
America Online: STARMAIL
CompuServe: 71561.2751
Internet: 71561.2751@compuserve.com

Please provide (or be prepared to provide) the following information when
ordering:
ú    The program you are registering (Ultra VGA Engine 32).
ú    Your mailing address.
ú    Your Visa, MasterCard or Discover card number and its expiration
date.
ú    Your drive type (if other than 3.5").
ú    Your e-mail address (so that NorthStar Solutions can send you
confirmation of your order).

IMPORTANT!
Please note that NorthStar Solutions only handles credit card orders.
They will not be able to offer any assistance or technical support with
any problems you may have with UVE32.  Please refer any such problems to
me directly.

Feel free to e-mail me as well, notifying me that you placed an order with
NorthStar Solutions if you want to speed up the sending out of the disk.

Other (non-credit card) orders

Apart by using a credit card, you can also register by the following
alternative methods:

ú    Cheque.  Must be in U.S. Dollars, British Pounds or Greek Drachmas
and made payable to "Constantine Prouskas".
ú    Cash.  Again, must be U.S. Dollars, British Pounds or Greek Drachmas.
For other currencies, visit your local bank or travel exchange.  You
should be able to convert to one of the above currencies using
international exchange rates.
ú    Direct deposit in a bank account (U.S., UK or Greece only).

Since addresses, bank accounts and the like are subject to change,
however, it's best if you contact me at the above address first (see the
"Contacting InterAction software" section).  Apart from notifying me that
you want to register, it is possible to work out the payment method that
is most convenient on a case-by-case basis (even using a method not
described above).  Additionally,  I can arrange sending out the registered
version via e-mail, if you so wish.

Epilogue

This, as they say, is it.  You can take it from here.  I've supplied the
tools, you supply the inspiration.

One final request:  If you ever use UVE32 to write any sort of application
(especially what it was meant for, games), I ask that you send me a piece
of mail saying what it is and where I can get it.  It's your way of
letting me know that all the hours of hard work that have gone into UVE32
have really paid off.

Go forth and make some magic.

# UVE\_KEY.TXT

UVE\_KEY

UVE\_KEY is a keyboard handler that can handle multiple keypresses, something
that the BIOS keyboard handler cannot, well... handle, but is essential even
for the simplest of games.

To install UVE\_KEY you must make a call to ia\_installkeyint.  This replaces
the BIOS' handler with UVE32's.  To de-install, you must call
ia\_restorekeyint.  This restores the BIOS handler to its previous state
(always do that before your program exits, otherwise the keyboard won't work
in DOS).  You can install and de-install the handler as many times as you
like within the program, provided that each installation call is matched with
a de-installation call.  Do not nest pairs of calls.

While UVE\_KEY is active, it will set the following variables:

np             This array represents the numeric keypad.
(array[1..2,1. The second index is the key number (1...9).
.9])           The first index is the 'player' index, and
is 1 for the right player (using the keypad)
and 2 for the left player (using the keys
QWE,ASD,ZXC)
shft           Shift keys.  Index 1 is the right shift key
(array[1..2])  (matches with player 1) and index 2 is the
left shift key.
esc            Escape key.
space          Spacebar key.
ctrl           Control key.
alt            Alt key.
return         Return key.
anykey         True when a key is pressed.  It is set based
on whether the last event was a key press or
a key release.  It will not detect multiple
keypresses.  It can be used to wait until
the user presses a key in the form:

repeat until anykey;

These variables are false when the corresponding key is not pressed and true
when it is.  They will remain true until the key is released  There is no
need to make an explicit call to any function to update their state.  This is
taken care of within the interrupt.

When lots of keys are pressed at once, some keys might not be recognized
correctly.  This is a limitation of the keyboard hardware and not of UVE\_KEY.
Also on some 101-key keyboards, some keys will show up incorrectly as
released if the cursor keys (inverted T shape) are used instead of the
keypad.  These situations arise when two players are using the keyboard (way
too many fingers), and should not pose a problem in a one-player game.

Note that when the handler is active, the BIOS is completely bypassed.  You
will not be able to use any of the standard keyboard I/O routines.  If you
do, the program will wait indefinitely for the BIOS to supply data, and you
will not be able to Ctrl-Break your way out of it.  So use carefully and save
often!  The upshot of this is that no other keys apart from the ones
controlled by UVE\_KEY can be tested (unless of course UVE\_KEY is removed).
That's usually OK, though, as you won't normally require the user to type
their name, address and social security number in the heat of battle.  Still,
if it is a problem, feel free to replace UVE\_KEY with the keyboard handler of
your choice.  Chances of incompatibilities are minimal.

# UVE32.RTF

**Version 1.40**

**Copyright (c)1996-97 Constantine Prouskas**

**InterAction software**

# Prologue

Right off the bat, I'd like to clear up some things:

·       Version 1.40 is the second public release of UVE32 and, as such, is still prone to various bugs and errors.  I've been using UVE32 for more than two years now and everything is pretty much ironed out, but *I* wrote it, and I'm sure someone out there will try something I had never thought of and crash it.  So, if you encounter any bugs, please report them to me and I will correct them in the next release.  Read the section on contacting InterAction software for further info.

·       UVE32 is shareware.  Try before you buy.  And we all know what *that* means.  If you like UVE32 and continue to use it, you must register it.  Registering not only clears your conscience, but also entitles you to free updates, loads of utilities and support.  Read the section on registering for more information.

# Quickstart

For those of you who are really, really in a hurry, take these steps to get you started:

·         Unzip UVE32.

·         Run BENCH.EXE to see if your VGA is fast enough for UVE32 animation.

·         Run UVEDEMO.EXE for an example of UVE32's capabilities.

·         Load up Pascal and run the examples provided.

·         Off you go!

# Requirements

What you need to run UVE32:

·       A computer.  I guess you have one of those already.  Must be at least a 386, though, because of the 32-bit code.  Not much of a limitation, if you ask me.

·       A VGA card.  The faster the better.

·       Turbo Pascal v6.0 or Borland/Turbo Pascal v7.0.

That's it.

# What's UVE32?

Let's start with the easy stuff.  UVE32 is a sprite-based graphics & animation unit for Turbo Pascal 6.0 & Borland/Turbo Pascal 7.0.  Drop to DOS and run BENCH.EXE and UVEDEMO.EXE to see an example of  what this baby can do.

UVE32 stands for *Ultra VGA Engine 32-bit*.  *Ultra* is there to distinguish UVE32 from the VGA Engine series, which is a set of three older libraries (VENGINE, VENGINE2 and VENGINE3).  UVE32 has been rewritten from scratch, using a different animation algorithm.  *VGA*because UVE32 supports only the VGA (CGA support is on the way ;-).  *Engine* because it provides the horsepower for an animation-intensive application, i.e. (who am I trying to fool) **GAMES**. *32* because it contains 32-bit code and is capable of running in protected mode. For the time being, 32 bit code is more or less useless because of Borland's 16-bit compiler, but is included for when a decent 32-bit compiler is released.

Here's a quick run-down of UVE32's features before we get started.

·         runs in VGA 320x200 256 colors

·         500 simultaneously active sprites

·         32K maximum sprite dimension (width/height)

·         64K maximum single sprite size

·         sprite chaining

·         sprite collision detection

·         automatic memory management

·         virtual coordinates in the -32K...+32K range

·         animation window

·         14 loadable fonts

·         static or scrolling background

·         transparency

·         translucency

·         palette maps

·         palette cross-fades

·         PCX support

·         FLI support

·         WAD file support

In my experience, sprite libraries can be divided into the following categories:

·       Easy to use (i.e., slow)

·       Powerful (i.e., extremely user-unfriendly)

·       Fast and user friendly (and written in C)

UVE32 offers an easy to use interface as well as low-level routines for squeezing out that last bit of potential.  If you are a beginner, you will find the interface very simple to use.  If you are more advanced, you will not be held back by the inherent limitations that inevitably come with easy user interfaces.

UVE32 might not run well on your system, depending on your VGA card.  If you are one of those people that read the documentation before running every executable in sight (fat chance), I suggest you drop to DOS and run the demonstration and the benchmarking program to discover if everything runs as expected.  Unless your VGA is a painfully slow one, however, I don't expect you will run into any difficulties.

Before we get into the intricacies of UVE32, take a moment to read the License Agreement, which contains some important information concerning the use of  UVE32.

# License Agreement

InterAction software grants you the right to use Ultra VGA Engine 32 ("UVE32").  For purposes of this section, "use" means loading UVE32 into RAM, as well as installation on a hard disk or other storage  device.

You may use the shareware version of UVE32 for a period of 21 days, after which you must either delete it or obtain the registered version.

You may freely distribute, transmit and store the shareware version of UVE32 on any electronic media, including but not limited to floppy diskette, hard disk, CD-ROM or other storage device, provided that you do not remove, edit, modify, or otherwise alter the original files of UVE32.  You may not distribute the registered version of UVE32.

You may not modify, translate, disassemble, decompile, reverse engineer or create derivative works (excluding software that uses UVE32 directly) based upon UVE32.

You may use UVE32 in your own software, provided that you have complied with the registration requirements set forth by InterAction software.  You may not use the shareware version of UVE32 in any piece of software that will become publicly available, including but not limited to public domain, freeware, shareware and commercial/retail software.

UVE32 is copyrighted by InterAction software and is protected by international copyright laws and international treaty provisions.  You must treat UVE32 like any other copyrighted material.  You

agree to use your best efforts to see that any user of UVE32 licensed hereunder complies with this agreement.

This software and accompanying written materials (including instructions for use) are provides "as is" without warranty of any kind. Further, InterAction software does not warrant or make any guarantees representations regarding the use, or the results of use, of the software or written materials in terms of correctness, accuracy, reliability, currentness, or otherwise. The entire risk as to the results and performance of the software is assumed by you.

The above is the only warranty of any kind, either expressed or implied, including but not limited to, implied warranties of merchantability or fitness for a particular purpose.  In any case, InterAction software shall not be liable for any direct, indirect, consequential or incidental damages (including damages for loss of business profits, business interruption, loss of business information and loss of data) arising out of the use or inability to use UVE32, even if InterAction software has been advised of the possibility of such damages.

You acknowledge that you have read this agreement, you understand this agreement, and understand that by continuing the installation of UVE32, by loading or running UVE32, or by placing or copying UVE32 onto your computer hard drive, you agree to be bound by this agreement's terms and conditions.

# Technical Information

NO!  NO!  NO!  I said READ the License Agreement, not SKIP OVER it!  As boring as it sounds, you must read it before using UVE32.  You have?  That's OK, then.  Let's get moving.

Note:  This section contains, as the heading would suggest,  technical information.  You do not need to know anything contained in this section to use UVE32.  Instead, it's meant to provide some insight at how UVE32 works.  If you haven't got any experience with the VGA and the VGA hardware, it's best to skip this section altogether.

UVE32 runs in the standard VGA mode 0x13 (19 to you ten-fingered people).  That's your average 320x200 256-color mode supported by the BIOS in every VGA since, well, the EGA.  Okay, so it's only got one page and an odd aspect-ratio, but when it comes to rock-solid animation and simple code (the latter bearing the most weight for me personally), the fact is, you can't beat mode 0x13's non-banked linear bitmap organization.

UVE32 is based on a, for lack of a better term, page-copy algorithm.  To those of you familiar with dirty-rectangle animation, you can think of the whole screen as being a single dirty rectangle, updated each frame.  What does this mean?  It means that all preparation for a frame is done in non-displayable system memory area the same size as the screen (a "page").  Once the whole frame is complete, the "hidden" page is simply copied onto the visible screen.  You might think copying the whole screen every frame is overkill; and you'd be right (didn't expect me to say that, did you?), but only in light load conditions.  In heavy load conditions and in cases where the whole screen changes from frame to frame (such as in panning around a virtual background), this is much faster than trying to maintain a list of updated areas and optimizing it so that each pixel is drawn once and only once.

I'd like to take a moment to point out that when I came up with this sort of algorithm, I didn't have a clue about page-flipping (or any other animation technique, for that matter), and it seemed like the intuitive thing to do.  I have to admit, though, that, even now, I would be hard pressed to find another algorithm that can deliver flawless frames given an adequately fast VGA.  Also, a little known fact is that page-flipped modes are built around the VGA's vertical sync/retrace signal, which cannot be relied upon, because there is no specification about exactly when it should occur.  Some of the other page-flipped libraries around flickered hideously when I ran them on my computer.

All drawing is done in system memory, which is much faster that video memory.  Since the image has to be copied to video memory in the end, however, video memory speed becomes the ultimate bottleneck, and, believe me, a narrow bottleneck it is.  On my slow ISA VGA, video access takes 50% of a 50-ms frame.  It can get much worse than this, though.  Some VGAs in my university lab (no names, please) take more than 500ms to copy the page onto display memory.  FIVE HUNDRED milliseconds for a maximum of under 2 frames per second!  You need not worry if you have a local bus VGA, however, and I've found that all Trident-based cards I've tested peak at about 20fps, which btw is fine for animation.  On a typical 486-33 with a local bus VGA, a sustained rate of 35-40 frames per second is not extraordinary.

Apart from the VGA access time bottleneck, another potential problem is shearing.  Shearing occurs when the VGA is scanning displayable data while the CPU is copying from the hidden page to the visible page.  Let's just say for a second that the CPU cannot copy data as fast as the electron beam sweeps the screen (usually 70Hz).  Let's also assume that the electron beam starts scanning when the CPU is halfway through copying data, and that it catches up with the CPU at some point within the displayable data area.  Everything displayed up to that point will belong to the new frame, and everything below will belong to the old frame, since the CPU hasn't had a chance to update it yet. The result will be a frame composed of parts of two different frames.

Shearing is bad, but not as bad as you might think.  It is only noticeable on a slow VGA, with a continuously scrolling background of specific pattern types and even then, it registers as some sort of flicker (not the type you're used to, just some sort of color dimming at specific scanlines of the screen).  Shearing is inherent to beam scanning anyway, since the screen is not updated all at the same instant.  If your VGA is capable of copying the whole page in the 70Hz time window, then shearing should not pose a problem.  In my experience, you can only see it when a disk caching program kicks in and writes to disk during the memory move (btw, in UVE32, interrupts are not disabled during a memory move).

# UVE Theory

## Frames

Note:  This section, despite being the basis of everything else, contains a lot of forward references.  If you don't understand what's going on, simply go on and come back once you've read the rest of the UVE32 theory.

Frames are the building blocks of animation.  They are the same type of frames used in traditional cinema and television animation.  A typical UVE32 frame cycle goes as follows:

·         First, the background is copied onto the workarea (the *hidden*page), erasing everything from the previous frame.

·         The scrolling background, if enabled, is constructed and placed on top of the background.

·         The sprites are copied, with sprite 500 going first and sprite 1 last.  This means that, as viewed on the screen, sprite 1 is on top and sprite 500 is at the very bottom.

·         The frame is now complete and is made visible on the screen.

·         If there is still time, UVE32 waits until the extra time expires before starting on the next frame.

I didn't know when I first built UVE32, but the same frame technique is used by *Mortal* *Kombat* and *Quake* (in videomode 0).  It's the most efficient way to do animation when the whole screen changes from frame to frame.  If you know of any more games that use this technique, I'd like to hear from you.

Related functions:

procedure ia\_waitretrace;

procedure ia\_doframepart1;

procedure ia\_doframepart2;

procedure ia\_doframepart3;

procedure ia\_doframe;

procedure ia\_setcycletime (i:integer);

## Pages

A page is simply a region of memory that can hold a 320x200 image (actually it's a bit more that that, but who's counting).  UVE32 has 4 predefined pages, on top of which you can declare your own, should that be necessary.  These are:

### The VGA page

The *vga* page is the only page of the four that is visible to the user.  This page holds the contents of the visible screen, and any change to that page will be immediately visible.

### The Hidden page

The *hidden* page is where virtually all work takes place.  To avoid all complications relating to updating the *vga* page in real time, the frame is first prepared in the *hidden* page and, once it is complete, is copied onto the *vga* page, thus becoming visible.

### The Background page

The *background* page holds, rather unsurprisingly, the background image.  At the beginning of each frame the *background* page is copied onto the *hidden* page to erase everything that was previously there and start fresh for the new frame.

### The Tiles page

The *tiles* page is not used for drawing, but is rather an area of memory that tiles are stored in.  It can hold up to 255 16x16 tiles.  Note that this page is not automatically allocated, as it is not needed if there is no scrolling background.  UVE32 will automatically allocate this page once *ia\_setscrolling* (which enables a scrolling background) is called.

Related functions:

procedure ia\_copypage (source,dest:word);

procedure ia\_putpixel (where,x,y:word;c:byte);

function ia\_getpixel (where,x,y:word):byte;

procedure ia\_hline (where:word;x,y,len:integer;c:byte);

procedure ia\_vline (where:word;x,y,len:integer;c:byte);

procedure ia\_line(where:word; x1,y1,x2,y2:integer;color:byte);

procedure ia\_box (where:word;x1,y1,x2,y2:integer;c:byte;filled:boolean);

procedure ia\_box\_clip (where:word;x1,y1,x2,y2:integer;c:byte;filled:boolean);

procedure ia\_cls (where:word;col:byte);

procedure ia\_fadein (where,time:word);

procedure ia\_newpage (var p:pagepointer; var where:word);

## Sprites

A sprite is, simply put, an animated graphic object on the screen.  An example to illustrate: in PAC-MAN, both the thing the player controls (moves) around the maze (that yellow circle with the big mouth; I suppose it's called the "pac-man") and the ghosts are sprites, in the sense that they are movable entities separate from something static like the background.

Now, I must confess that if this is the first time you hear about sprites, you are probably totally confused by my explanation; and anyone short of a nuclear scientist would be.  The best solution is to run some of the examples included with UVE32 to get an intuitive idea about what sprites are.  For the rest of this discussion, I will assume that you understand the word sprite has nothing to do with fairies or pixies in this context.  (Although, just to confuse you more, it is possible to have a sprite that looks like a fairy.  On second thought, forget I just said that.)

A sprite is an object that has coordinates (so it can move around) along with some other attributes, the most important of which is what it looks like; that is, what it's physical representation on the screen is.  A sword, a dragon, a monster, all these are different sprites in the sense that what you see on the screen can be uniquely identified by its appearance.  Often the term sprite is used to refer to the picture that is visible on the screen, but that's not what I am going to follow, because beginners will get completely lost.

To recap:  A sprite is an object that has coordinates along with other attributes, and which is linked to its image, its likeness, its semblance, which is a picture that is used to represent that sprite on the screen.  That picture is not necessarily unique.  For example, ten swords displayed on the screen are ten different sprites, in the sense that each one is individually controllable.  However, they are all linked to the same image.  They are ten different objects with a common appearance on the screen.

I will use the term "sprite" when referring to an object and the term "image" when I am referring to the picture that represents the sprite.

The reason the sprite is different from its image is memory constraints.  Imagine 100 identical swords displayed on the screen.  Clearly, to store the same image 100 times along with each sprite would be clearly a waste of memory space.  We therefore separate the image from the sprite, and from within the sprite structure, we select one of the available images to represent it.

### Loading sprite images

Okay.  Before an image can be used, it must first be loaded into memory.  In UVE32, there are 500 slots (positions) for images to be placed in, from 1 to 500 (0 has a special meaning, as we will soon see).  Each slot can be thought of as a pigeon-hole that can hold a single image.  Let's say there's a file called "pacman.uvs" that contains an image  and you want to load it into slot 7.  You don't need to worry about memory allocation and the like, you just say

ia\_loadspr ('pacman.uvs',7);

Note that, although the function name is *ia\_loadspr*, it doesn't load a sprite (sprites cannot be "loaded" in the normal sense); it loads an image.  At this point it might be a good idea to refer to the examples to see how images are loaded.

A slight digression:  .UVS files hold a single sprite image, whereas .UVL files hold multiple images that are loaded into consecutive locations.  UVE32 automatically detects whether a given file holds a single or multiple images, so you don't need to stick to the extensions (but it's better if you do, because some UVE32 utilities assume default extensions).

It is important to realize that loading an image into memory does not display it on the screen in any way. This is so important it bears repeating.  Loading an image does not cause anything to be displayed on the screen.  You are simply loading an image and putting it into one of the 500 available slots.  The number of the image's slot is the image's id; the way in which it will be referred to when you want to use it.  Continuing the example above, every time you want to use the image 'pacman.uvs', you will refer to it by using the number 7, the number of it's slot.

As a sidenote, UVE32 sprites are use a proprietary RLE & zero-byte variant compression method for fast rendering.  This offers great performance but screen-space clipping is hell.  I definitely wouldn't recommend it to the faint-hearted :-)

Related functions:

procedure ia\_loadspr (filename:string; n:integer);

### Displaying a sprite

Now that the image has been loaded, we need to define a sprite and link it to that image.  Up to 500 sprites can be simultaneously defined (ranging from 1 to 500).  As mentioned earlier, defining a sprite is as simple as linking it to an image, so it possesses an external, physical representation and therefore is able to be displayed.  This is easily done, if we remember that each image has it's own unique slot number.

A sprite is defined by linking it to an image.  As soon as a sprite is linked to an image, it is displayed (not instantly, though; you have to wait until a frame occurs).  Sprites are held in an array of 500 elements, with each item being a single sprite.  This array is called *spr*.  So, if we want to access the 10th sprite we would do something along the lines of

with spr[10] do

begin

...

end;

So, how do we link the image with the sprite?  Couldn't be easier.  No, really.  Simply set the *n* field of the sprite in question to the number of the image slot.  So, from above, if the pacman is loaded into slot 7:

with spr[10] do

begin

n:=7;

end;

or simply:

spr[10].n:=7;

Done!  Now, in the next frame, the sprite will appear at (0,0) screen coordinates.  Of course, in a real application, some of the other fields should be set accordingly.  A sprite is disabled (not displayed) by setting the *n* field to zero.  In fact, this is the default value for all sprites after calling *ia\_inituve*.

A word of caution, however.  If you link a sprite to an image that has not been loaded, the results will be unpredictable (okay, okay, it will most likely crash the program).  So always, always make sure that the image the sprite is linked to is loaded.  This might seem an easy thing to do, but it gets a bit more complicated when you are dealing with more sophisticated features such as chained sprites.  And with that, on to chained sprites.

Related functions:

procedure ia\_displaysprite (n:integer;destofs,destseg:word);

procedure ia\_displaysprite\_mapped (n:integer;destofs,destseg:word;m:byte);

procedure ia\_displaysprite\_transparent (n:integer;destofs,destseg:word;m:byte);

### Sprite Chaining

In a real application, sprites rarely have a constant image throughout the program.  Most likely, you will want the hero you are controlling to move his legs when he is walking instead of sliding on the ground.  What this means is that you will need to change the image that is linked to the sprite.  This is easily done by setting *n* to a new number.  When dealing with many sprites, however, this can become extremely difficult to keep track of.  On top of that, some sprites loop through some predefined frames of animation.  A fire, for example, can loop through five different images to give the appearance of burning.  Can UVE32 help when it comes to this kind of bookkeeping?  You bet.

Images are kept in an array called *ln*(the full description of the array field is given at the end).  When you are loading a sprite in a slot, you are simply giving the array index of that slot.  Each array item holds pointers to the image data and collision detection information (stuff you don't need to know about) along with the image's width, height (which are handy to know about) and *next* field (which you do need to know about).  The *next*field is the number of another image slot.  Each frame, every sprite that is linked to an image slot will be linked to the image slot specified in the *next*field.  Take a moment to re-read the above sentence.  An example will make things clear (hopefully):

Assume that image slot number 7 has a *next* field with a value of 220.  This means that any sprite which is linked to image slot 7 (i.e. *spr[...].n:=7*), after a frame occurs, will be linked to image slot 220 (i.e. *spr[...].n:=220*).  After yet another frame, sprites linked to image slot 220 will be linked to the number of that slot's *next*field.  By default, a slot's *next* field is initialized to the same slot number (i.e. *ln[x].next:=x*).  This means that the sprite doesn't change it's image over time.  You can change that, however.

The "chain" can be completely arbitrary, but what's usually chained are images with consecutive slot numbers.  This is so because the *ia\_loadsprite* function is capable of loading multi-image files into consecutive slots.  Anyway, even if images are loaded one by one in consecutive locations, they can easily be chained using:

ia\_chainsprite (start slot, chain length, end slot);

The start slot is the first slot in the chain.  The chain length is the number of slots in the chain.  The end slot is what the *next* field of the final chain slot will be set to.  To create an infinite loop, set end slot=start slot.  To create a disappearing sprite, set end slot=0.  In my games, I have frequently used missile smoke sprites.  These consist of a few chained frames of a puff of smoke (decreasing in size), with the final slot pointing to 0.  So, I can simply define a smoke sprite and let it take its course, without worrying about when I should delete it.  It will simply be deleted by itself when the time comes.  (Another, more general, way is to set the *life* field of the *spr* array, as will be explained further down the road.)

If you have created a chain, you can pick it up at any point.  For example, if you have ten fires that you don't want to burn in sync with one another, you can set their starting slots at different values within the chain.  Check the examples for some, well, examples of this.

Related functions:

procedure ia\_chainsprite (nr,len,endloop:integer);

procedure ia\_unchainsprite (nr,len:integer);

### Moving sprites

Sprites have coordinates, as specified by the *x* and *y* fields of *spr.*  Sprites move by changing these coordinates.  The coordinates are virtual coordinates, in the integer range -32K to 32K in pixels.  If a sprite lies outside the displayable area, it will not be displayed.  If it is partially visible, it will be clipped.  Note that sprite visibility is not a prerequisite for sprite collision.  Sprites can collide even outside the visible area.

You can pan around the virtual world (i.e. change the visible area) by setting *vpx* (viewport x) and *vpy* (viewport y) to appropriate values.  If you have selected a scrolling background, it will scroll appropriately.  The viewport always spans (*vpx*,*vpy*)-(*vpx*+319,*vpy*+199).  (*vpx*,*vpy*) always maps to the top left of the screen, even if an animation window has been defined.

Related functions:

function ia\_visiblex(i:integer):boolean;

function ia\_visibley(i:integer):boolean;

function ia\_visible(i:integer):boolean;

procedure ia\_center(i,x,y:integer;pos:byte);

### Sprite collision

Perhaps one of the most important aspects of sprites is the ability to detect if two of them overlap ("collide").  After all, you wouldn't want your missiles to whiz right through the enemy ships, would you?  In UVE32, sprite collision is pixel-precise (with a few exceptions).  Bounding boxes are not used, as they are very infuriating when dealing with 2D graphics ("But that missile didn't touch me!  I'm telling you it didn't touch me!").  You are free to use the *width*and *height* variables to implement such an algorithm, however.

To speed up collision detection, sprites are assumed to be vertically and horizontally monotone, i.e. a vertical or horizontal line through the sprite intersects its edges only twice.  Think of it as the sprite being convex, only it includes and some cases of non-convex sprites.  Holes are out of the question.  Another way of putting it is assuming that every pixel between the leftmost and rightmost non-black pixels in each line (and similarly topmost and bottommost for vertical lines) is considered to be part of the sprite, and therefore can collide with another sprite.  This requires extra collision data to be stored along with the image data.  UVE32 takes care of that for you automatically.  All you need to remember is to tick the "save collision data" box when saving sprites through the utilities provided.

Sprite collision between two sprites can be detected by calling *ia\_collide*, which will return *true* if the two sprite indices provided as parameters overlap.  Caution!  You must make sure that both sprites have collision data embedded in them.  UVE32 does not check for that, and will use garbage data for collision, if none is available.

A couple of notes on sprite collision.  Sprites can collide in the 64Kx64K virtual world, even outside the screen area.  A sprite cannot collide with itself.  Inactive sprites cannot collide (sprites for which *n*:=0).  Another thing is that when there is obvious biasing towards sprite size in collision pairs (as in the case of missile-spaceship, where the missile is usually smaller than the ship), you will speed up collision check if you pass the smallest sprite as the first parameter.

Related functions:

function ia\_collide(a,b:integer):boolean;

### Deleting sprites & images

Images can be deleted but, in my experience, it's rarely necessary.  Should the need arise, you can call *ia\_delspr* to delete an image.  If you load an image on top of a filled slot, the old image will be deleted and memory will be freed before the new one is loaded.

Sprites are a different matter altogether.  They cannot be deleted in the normal sense.  They are "deleted" by setting the *n* field to zero.  Another way is to set the *next* field of some image slot to zero, as described in the section about sprite chaining.  Yet another way is to use the *life* field, which simply holds the number of frames left for which the sprite will be visible.  Once this counter counts down to zero, the sprite is deleted (i.e., not displayed).  When a sprite is not displayed, other sprite fields remain unchanged, so if you want a sprite to blink, you can toggle the *n* field between zero and some non-zero value.

Related functions:

procedure ia\_delspr (n:integer);

### Other sprite attributes

For completeness, here is the whole sprite structure:

type  scb         =record

x,y,                              sprite coords

n,                          sprite loadnumber

life                  :integer;   frames left, if 0 ® n:=0

transparent     :boolean;         use sprite/background data

map             :byte;            which palette mapping to use

end;

*Transparent* specifies whether to use actual sprite data or the underlying background data.  Why is that useful?  If *map* is zero, specifying that no palette map will be used, then displaying the sprite will use the background colors, in effect making it invisible.  That's of limited use (although I've used it in a game).  If *map* is non-zero, however, background colors will be mapped.  If the palette mapping used is, say, one where each color maps to another of 70% brightness, then the net effect will be a sprite that looks like a shadow.  Check the examples and the palette maps section for more info.

And similarly, for the sprite images:

loaded            =record

data                  :pointer;  pointer to sprite data

collength,                        length of collision data

length,                     size in memory

width,height    :word;       size of sprite

next                  :word;            sprite sequence

end;

loadedarray       =array[0..nspr] of loaded;

Related Functions:

procedure ia\_setspritesused (i:integer);

procedure ia\_setclipdepth (i:integer);

procedure ia\_setwindow (x1,y1,x2,y2:integer);

## Palettes

A palette is simply a set of 256 colors, each of which is comprised of red, green, and blue values in the range 0-63.

palcolor          =record

red,green,blue:byte

end;

palette           =array[0..255] of palcolor;

You can define your own palettes, but UVE32 has two predefined palettes called *blackpal*and *pcxpal.*  *Blackpal* is simply a palette where all the colors have RGB triplets of (0,0,0) (i.e. they are all black).  Very handy for those fade-ins/fade-outs.  *Pcxpal* is where the last loaded .PCX's palette is stored.  Loading a .PCX file does not automatically set the palette.

Finally, a note on setting the palette.  Continuously setting the palette DAC (as happens in fade-ins/outs) can cause "snow" to appear on the screen.  The effect can range from minimal to a complete snowstorm.  There is no way around this, except inserting a delay between palette sets and/or synchronizing to the VGA vertical retrace signal.  UVE32 protects against these effects by synchronizing with the vertical retrace signal.  As all clones are not created equal, however, this does not guarantee that it will work on your system.  If you experience snow, stay in until the sun comes out :-)

Related functions:

procedure ia\_setpalette (pal:palette);

procedure ia\_getpalette(var pal:palette);

procedure ia\_loadpalette (filename:string; var p:palette);

procedure ia\_fadeto (s,t:palette; steps:word);

procedure ia\_weirdfadeto (s,t:palette;d:integer);

## Palette maps

Palette maps are color look-up tables (CLUTs) that map each of the 256 colors to another color index.  They do not define new color values.  UVE32 defines *maparray*which holds 5 palette maps.

maparray          :array[1..5] of maptab;

These maps can be applied to sprites by setting the *map* field of the *spr* structure to the color map index (1-5) of the palette map to use.  In such a case, the sprite is not displayed in its normal colors, but goes through a look-up stage.  Example time:  imagine that *maparray[1]* has all its entries set to 255:

for i:=0 to 255 do maparray[1][i]:=255;

Then, if the *map*field of a sprite is set to 1, then every pixel of the sprite will be displayed as color 255.  Again, the best way to understand how these things work is to take a look at the examples.

Apart from defining a maparray entry manually, you can use *ia\_makeshadowmap* and *ia\_makeglenzmap*, which set a map automatically.

Related functions:

function ia\_findclosestcolor (var p:palette; r,g,b:integer):byte;

procedure ia\_makeshadowmap (var p:palette; percent:integer;var mapped:maptab);

procedure ia\_makeglenzmap (var p:palette; xr,xg,xb:integer;var mapped:maptab);

## Tiles

The *background* page holds a static image.  You can have a larger image that you can pan around, however.  The memory required to store such an image is prohibitive, so the image is composed of smaller 16x16 pixel images called tiles. You can have as many as 255 tiles that make up an image up to 5020 (stupid number, but don't ask) tiles in size (width x height). Think of tiled floors or sidewalks and how a single tile can be repeated to fill a larger area, only here you have a choice of 255 tiles to place at each position.

In order to set up the scrolling background, you must first call *ia\_setscrolling*.  This allocates memory for the tiles.  Your tile area can have any dimension, as long as the total tiles do not exceed 5020.  You set your desired tile area with *ia\_setscrollarea*.  Note that the width and height parameters are given in tiles, not pixels.

You can scroll around the tiled imaged by changing the *vpx*and *vpy* variables, which define the coordinates of the top-left of the screen into your virtual world.

Tiles cannot have transparent areas.  If part of a tile is drawn in black, then a black pixel will be placed on the screen.  The static background will not show through.

If you pan out of the defined tile area, the screen is filled with the tile at index 0.  In other words, the area outside of the tile area is assumed to be filled with tile 0.

If your animation window is smaller than the screen, then the outside will show the static background image.  If you intend to use the whole screen, however, you can speed things up by not using the static background, since no part of the background will be visible.  You can disable the static background with the *usebackground*variable.

If you intend to use tiled backgrounds along with windowed animation, read the bugs section for an important limitation.

Related functions:

procedure ia\_loadtil (filename:string; n:integer);

procedure ia\_displaytile (n:byte; lineofs,destseg:word);

procedure ia\_setscrolling;

procedure ia\_setscrollarea(x1,y1,w,h:integer);

procedure ia\_puttile(x,y:integer;n:byte);

function ia\_gettile(x,y:integer):byte;

procedure ia\_setstatic;

## PCXs

UVE32 is capable of loading Zsoft's popular PCX file format pictures.  The header is ignored, however, so PCX files must be exactly 320x200 in size, with 256 colors.  Loading a PCX does not set its palette.  The palette is automatically saved in the *pcxpal* variable.

Related functions:

procedure ia\_loadpcx (where:word;filename:string;seethru:byte);

## Fonts

UVE32 uses BIOS mode 0x13, so there should be no problem displaying text by calling standard procedures such as *writeln*.  Personally, I've never, ever used the BIOS to print text.  Printing text in this way uses the built-in (i.e., ugly) font.  On top of that, the background is destroyed. Have no fear, though, because UVE32 is here to get you out of another mess.  With its 15 fonts, horizontal and vertical printing, background preservation, shadows, textures, proportional and fixed spacing, it's everything the font-conscious user might want (okay, maybe not).

First thing's first, though.  In order to use fonts, some steps must be taken.

·         The file UVE.UVW must be in the current directory.

·         You must load the font into memory by *ia\_loadfont*.  All of the 15 fonts can be present in memory at the same time.

·         You must call *ia\_setfontattr* to set the desired font attributes.

·         Finally, you can print text by calling *ia\_printstr*.

The 15 built-in fonts must be referred to by index number.  Okay, so an enumeration would be a better idea, but no-one is stopping you from creating one!  The fonts are:

Take note of a few things when dealing with fonts.  First, make sure you load the font before using it, otherwise you get a cryptic error message about dereferencing a null pointer.  Second,  in the interest of speed, no clipping is performed.  Third, the fire texture makes use of the palette colors 224-245, so make sure you place your desired colors there (for example, a red-yellow-white gradient). Fourth, whatever you do, never, EVER try to .... oops, slipped my mind :-).

Related Functions:

procedure ia\_setfontattr (a:byte; b:fonttextures; c:fontcpi; d:fontorient; e:byte; f:boolean; g:byte);

function ia\_strlength (s:string):word;

procedure ia\_printstr (where:word;xx,yy:integer; s:string; clr:byte);

procedure ia\_loadfont (i:byte);

## FLIs

UVE32 is capable of loading and playing Autodesk .FLI files.  Before you play any .FLI file you must make a call to *ia\_setfliparameters*to set some parameters such as looping and play rate.   Apart from that, playing .FLI files is as easy as calling *ia\_playfli*.  You can have more control over the way a .FLI file is played by reverting to a lower-level interface.  Check the functions & procedures section for more info.

Related functions:

procedure ia\_openfli(filename:string);

procedure ia\_playframe;

procedure ia\_wait4nextframe;

procedure ia\_closefli;

procedure ia\_setfliparameters(a:integer;b:word;c:boolean);

procedure ia\_playfli(s:string);

## WAD files

It is possible to combine all the read-only files (i.e., not files such as config and highscore files, which are written to) that your application needs in a single master wad file.  UVEDEMO uses such a file (UVEDEMO.UVW).  UVW files are not fully supported in the shareware version.  All the relevant code is there, but you need to register to be able to create them.

Related functions:

procedure ia\_setwadfile (s:string);

function ia\_searchinwad (var fp:file;lookingfor:string):longint;

# UVE Interface

## Unit interface section

const nspr        =500;             maximum number of sprites

maxtiles    =5020;                  maximum number of scrolling area in tiles

type   scb        =record

x,y,                              sprite coords

n,                          sprite loadnumber

life                  :integer;   frames left, if 0 ® n:=0

transparent     :boolean;         use sprite/background data

map             :byte;            which palette mapping to use

end;

scbarray    =array[0..nspr] of scb;

loaded            =record

data                  :pointer;   pointer to sprite data

collength,                        length of collision data

length,                     size in memory

width,height    :word;       size of sprite

next                  :word;            sprite sequence

end;

loadedarray       =array[0..nspr] of loaded;

maptab                  =array[0..255] of byte; used for colormapping

fontorient        =(horizontal,vertical); font attribute types

fontcpi           =(fixed,proportional);

fonttextures            =(plain,fire);

pagetype          =array[0..$FFFE] of byte;

pagepointer       =^pagetype;

palcolor          =record

red,green,blue:byte

end;

palette           =array[0..255] of palcolor;

var   vpx,vpy           :integer;                        viewport topleft corner coords

hidden                  :word;                  segment of the hidden page

hiddenpoint       :pagepointer;     pointer to hidden page

background        :word;            segment of background

backgroundpoint   :pagepointer;     pointer to background

tiles             :word;                  segment of tiles

tilespoint        :pagepointer;     pointer to tiles

pcxpal                  :palette;         last PCXs palette

blackpal          :palette;         all blacks (0,0,0)

spritesloaded     :integer;         set by last "loadSPR" call

retraceenable,                      wait 4 vertical retrace?

usebackground     :boolean;         copy bg to hidden page?

developermode     :boolean;         show developer stats

maparray          :array[1..5] of maptab;

these tables are uses to map

colors when display method

is eg shadow, glenz, ...

spr               :scbarray;

ln                :loadedarray;

vga               :word;

lastframe         :boolean;

textenable        :boolean;                   enables uve\_text

fliframenumber    :word;                  number of current FLI frame

frame             :integer;         current uve frame number

## Other variables

·       *spritesloaded:*Sprites loaded by last *ia\_loadspr* call

·       *retraceenable (false):*If true, UVE waits for a vertical retrace signal before copying the *hidden* page to the *vga* page.  This is not needed, but included for the sake of completeness.  In the unlikely case you are experiencing screen flicker, turn this option on.  Minimizes flickering, but slows down frame rate.

·       *usebackground (true):*If true, UVE will copy the *background* page to the *hidden* page before anything else to clear the last frame.   If you've got a full-screen scrolling background, however, this is not necessary.  Turning this option off will improve frame rate.

·       *developermode (false):*When true, displays a bar on the top-left of the screen with some statistics.  Each pixel in the graph corresponds to 1 millisecond:

·       White portion represents time spend by UVE rendering the screen.

·       Blue portion represents time taken by your program apart from rendering time.  This includes game logic time, collision checks, keyboard input etc.

·       Red portion represents time taken to copy *hidden* to *vga* page.  The reason this is separate is that, depending on your VGA, it can take up to 90% of the total frame time.

·       White arrow under bar represents desired (set) frame rate.

Note that colors mentioned correspond to default palette.

·       *lastframe (false):*True if current FLI frame is the last frame.  Used for manual FLI play loops.

·       *textenable (true):*Set to false if you don't want any text output from UVE (for example when loading sprites).  Output is always disabled when in graphics mode.

·       *fliframenumber (0):*Current FLI frame number

·       *frame (0):*Current UVE frame number

## Functions & Procedures

The functions and procedures of UVE are divided into four categories:  general-purpose, beginner, intermediate and advanced.  General purpose procedures are simple "utility" procedures.  Beginner entries include all procedures that you must absolutely know about in order to use UVE.  Intermediate entries refer to commands that you will use frequently when you've learned the ropes.  Advanced entries, finally, provide a lower lever interface to UVE and, as such, are more powerful and allow for extensive customization.  You do not have to know any of the advanced commands, but they do come in handy in certain situations.

### General Purpose Commands

function **i2s** (*i*:integer):string;

Purpose                  Convert an integer to its string representation

Parameters            *i*               Integer variable to be converted

Return                    String representation of *i*

Notes                      -

See also                 **l2s**, **w2s**

function **w2s** (*w*:word):string;

Purpose                  Convert a word to its string representation

Parameters            *w*             Word variable to be converted

Return                    String representation of *w*

Notes                      **i2s**, **l2s**

See also                 -

function **l2s** (*l*:longint):string;

Purpose                  Convert an long integer to its string representation

Parameters            *l*               Longint variable to be converted

Return                    String representation of *l*

Notes                      -

See also                 **i2s**,**w2s**

function **max**(*a*,*b*:integer):integer;

Purpose                  Return greater of two numbers

Parameters            *a,b*          Integers to be compared

Return                    Greatest integer

Notes                      -

See also                 **min**

function **min**(*a*,*b*:integer):integer;

Purpose                  Return smaller of two numbers

Parameters            *a,b*          Integers to be compared

Return                    Smallest integer

Notes                      -

See also                 **max**

procedure **ia\_checkfile** (*s*:string);

Purpose                  Check whether a file exists

Parameters            s              Filename

Return                    -

Notes                      Calls **ia\_erro*r*** if file does not exist

See also                 -

procedure **ia\_checkmem** (*w*:word);

Purpose                  Check for available memory

Parameters            *w*             Requested memory in bytes

Return                    -

Notes                      Calls **ia\_error** if free memory is less than *w*

See also                 -

### Beginner Commands

procedure **ia\_loadtil** (*filename*:string; *n*:integer);

Purpose                  Load a tile

Parameters            *filename*                UVT or UVL file name

*n*              Index of tile

Return                    -

Notes                      Calls **ia\_error** if file is not found

See also                 **ia\_setscrolling**, **ia\_puttile**, **ia\_gettile**, **ia\_displaytile**

procedure **ia\_loadspr** (*filename*:string; *n*:integer);

Purpose                  Load a sprite

Parameters            *filename*                UVS or UVL file name

*n*              Index of sprite

Return                    -

Notes                      Calls **ia\_error** if file is not found

Sets *spritesloaded* to the number of sprites loaded

See also                 **ia\_delspr**

procedure **ia\_loadpcx** (*where*:word; *filename*:string; *seethru*:byte);

Purpose                  Load a PCX file

Parameters            *where*     Page segment

*filename*                PCX file name

*seethru*   Transparent color (255=none)

Return                    -

Notes                      PCX palette is stored in *pcxpal*

See also                 -

procedure **ia\_setpalette** (*pal*:palette);

Purpose                  Set the current palette

Parameters            *pal*          Palette to set

Return                    -

Notes                      -

See also                 **ia\_loadpalette**,**ia\_getpalette**

procedure **ia\_loadpalette** (*filename*:string; var *p*:palette);

Purpose                  Load a palette

Parameters            *filename*                PAL file name

*p*              Palette variable to store result into

Return                    -

Notes                      -

See also                 **ia\_setpalette**, **ia\_getpalette**

procedure **ia\_setscrolling**;

Purpose                  Set scrolling (tiled) background

Parameters            -

Return                    -

Notes                      Allocates *tiles* page first time it's called

See also                 **ia\_setstatic**

procedure **ia\_setscrollarea**(*x1*,*y1*,*w*,*h*:integer);

Purpose                  Set scrolling area

Parameters            *x1,y1*      Coordinates of top-left corner in pixels

*w,h*          Width and height of scroll area in tiles

Return                    -

Notes                      *x1,y1* are automatically aligned on a 16x16 grid

See also                 **ia\_setscrolling**

procedure **ia\_puttile**(*x*,*y*:integer; *n*:byte);

Purpose                  Set a tile on the scroll area

Parameters            *x,y*           Coordinates to place tile in pixels

*n*              Tile number

Return                    -

Notes                      *x1,y1* are automatically aligned on a 16x16 grid

See also                 **ia\_gettile**

procedure **ia\_setfontattr** (*a*:byte; *b*:fonttextures; *c*:fontcpi; *d*:fontorient; *e*:byte; *f*:boolean; *g*:byte);

Purpose                  Set font attribute

Parameters            *a*              Font number

*b*              Font texture.  Can be *plain* or *fire*

*c*              Character spacing.  Can be *fixed* or *proportional*

*d*              Font orienation.  Can be *horizontal* or *vertical*

*e*              Background color.  Use 255 for transparent background

*f*               True for a font shadow to be displayed

*g*              Shadow color

Return                    -

Notes                      *Fire* uses color indices 224-245

Font must be loaded first

See also                 **ia\_loadfont**, **ia\_strlength**, **ia\_printstr**

procedure **ia\_printstr** (*where*:word; *xx*,*yy*:integer, *s*:string; *clr*:byte);

Purpose                  Print a string

Parameters            *where*     Page segment

*xx,yy*       Coordinates where string printing will start in pixels

*s*              String to print

*clr*           String color

Return                    -

Notes                      Use *xx*=-32768 to center the string on screen

No clipping is performed

See also                 **ia\_loadfont**, **ia\_setfontattr**, **ia\_strlength**

procedure **ia\_loadfont** (*i*:byte);

Purpose                  Load a font

Parameters            *i*               Font number

Return                    -

Notes                      Calls **ia*\_*error** if *UVE.UVW* is not present in the current directory

See also                 **ia\_setfontattr**, **ia\_strlength**, **ia\_printstr**

procedure **ia\_powerup**;

Purpose                  Switch to graphics mode 0x13

Parameters            -

Return                    -

Notes                      -

See also                 **ia\_shutdown**

procedure **ia\_shutdown**;

Purpose                  Switch to text mode 0x03

Parameters            -

Return                    -

Notes                      -

See also                 **ia\_powerup**

procedure **ia\_playfli**(*s*:string);

Purpose                  Play a FLI file

Parameters            *s*              FLI file name

Return                    -

Notes                      Calls **ia\_error** if file cannot be found

See also                 **ia\_setfliparameters**,**ia\_openfli**, **ia\_playframe**, **ia**\_**wait4nextframe**, **ia**\_**closefli**

procedure **ia\_inituve**;

Purpose                  Initialize UVE32

Parameters            -

Return                    -

Notes                      Call before anything else.

Call once only.

See also                 -

procedure **ia\_doframe**;

Purpose                  Execute frame

Parameters            -

Return                    -

Notes                      Calls parts 1,2 and 3

See also                 **ia\_doframepart1**, **ia\_doframepart2**, **ia\_doframepart3**

### Intermediate Commands

procedure **ia\_getpalette**(var *pal*:palette);

Purpose                  Get the current palette

Parameters            *pal*          Palette variable to store result into

Return                    -

Notes                      -

See also                 **ia\_loadpalette**,**ia\_setpalette**

procedure **ia\_setwadfile** (*s*:string);

Purpose                  Set the current UVW file

Parameters            *s*              Filename

Return                    -

Notes                      When *s* is specified, all PCX/UVS/UVL/FLI/UVT files will be loaded from *s*

To load files normally, call ***ia\_setwadfile***(*);*

Calls **ia\_error** if file does not exist

See also                 **ia\_searchinwad**

procedure **ia\_copypage** (*source*,*dest*:word);

Purpose                  Copy a page

Parameters            *source*    Source page segment

*target*     Target page segment

Return                    -

Notes                      -

See also                 -

procedure **ia\_cls** (*where*:word; *col*:byte);

Purpose                  Clear a page

Parameters            *where*     Page segment

*col*          Color to use

Return                    -

Notes                      -

See also                 -

procedure **ia\_putpixel** (*where*,*x*,*y*:word; *c*:byte);

Purpose                  Plot a pixel

Parameters            *where*     Page segment

*x,y*           Point coordinates

*c*              Color to use

Return                    -

Notes                      No clipping is performed

See also                 **ia\_getpixel**

function **ia\_getpixel** (*where*,*x*,*y*:word):byte;

Purpose                  Read a pixel

Parameters            *where*     Page segment

*x,y*           Point coordinates

Return                    Color of specified pixel

Notes                      No clipping is performed

See also                 **ia\_putpixel**

procedure **ia\_hline** (*where*:word; *x*,*y*,*len*:integer; *c*:byte);

Purpose                  Draw a horizontal line

Parameters            *where*     Page segment

*x,y*           Starting point coordinates

*len*          Line length in pixels

Return                    -

Notes                      Performs no clipping

See also                 **ia\_vline**, **ia\_line**

procedure **ia\_vline** (*where*:word; *x*,*y*,*len*:integer; *c*:byte);

Purpose                  Draw a vertical line

Parameters            *where*     Page segment

*x,y*           Starting point coordinates

*len*          Line height in pixels

Return                    -

Notes                      Performs no clipping

See also                 **ia\_hline**, **ia\_line**

procedure **ia\_line**(*where*:word; *x1*,*y1*,*x2*,*y2*:integer; *color*:byte);

Purpose                  Draw a line using Bresenham's algorithm

Parameters            *where*     Page segment

*x1,y1*      Start point coordinates

*x2,y2*      End point coordinates

*color*      Color to use

Return                    -

Notes                      Performs no clipping

See also                 **ia\_vline**, **ia\_hline**

procedure **ia\_box** (*where*:word; *x1*,*y1*,*x2*,*y2*:integer; *c*:byte; *filled*:boolean);

Purpose                  Draw a box

Parameters            *where*     Page segment

*x1,y1*      Start point coordinates

*x2,y2*      End point coordinates

*c*              Color to use

*filled*      If true, box is filled with color *c*

If false, only a hollow rectangle is drawn

Return                    -

Notes                      Performs no clipping

See also                 **ia\_box\_clip**

procedure **ia\_box\_clip** (*where*:word; *x1*,*y1*,*x2*,*y2*:integer; *c*:byte; *filled*:boolean);

Purpose                  Draw a box

Parameters            *where*     Page segment

*x1,y1*      Start point coordinates

*x2,y2*      End point coordinates

*c*              Color to use

*filled*      If true, box is filled with color *c*

If false, only a hollow rectangle is drawn

Return                    -

Notes                      Same as **ia\_box**, but performs clipping as well

See also                 **ia\_box**

procedure **ia\_fadein** (*where*,*time*:word);

Purpose                  Dissolve a page onto the VGA page

Parameters            *where*     Page to be dissolved

*time*        Speed of transition

Return                    -

Notes                      Very slow on some 386s

See also                 -

procedure **ia\_makeshadowmap** (var *p*:palette; *percent*:integer; var *mapped*:maptab);

Purpose                  Make a shadow map

Parameters            *p*              Palette variable to use as a base for mapping

*percent*  Shadow percentage

*mapped*  Map table variable to store result into

Return                    -

Notes                      *Percent* can be more than 100, which will result in a brighter colormap

See also                 **ia\_findclosestcolor**, **ia\_makeglenzmap**

procedure **ia\_makeglenzmap** (var *p*:palette; *xr*,*xg*,*xb*:integer; var *mapped*:maptab);

Purpose                  Make a glenz (translucency) map

Parameters            *p*              Palette variable to use as a base for mapping

*xr,xg,xb*  RGB components to add to each color

*mapped*  Map table variable to store result into

Return                    -

Notes                      *xr*,*xg*,*xb* can be positive or negative

See also                 **ia\_findclosestcolor**, **ia\_makeshadowmap**

procedure **ia\_fadeto** (*s*,*t*:palette; *steps*:word);

Purpose                  Cross-fade between two palettes using linear interpolation

Parameters            *s*              Source palette

*t*               Target palette

*steps*       Cross-fade duration

Return                    -

Notes                      -

See also                 **ia\_weirdfadeto**, **ia\_loadpalette**, **ia\_setpalette**, **ia\_getpalette**

procedure **ia\_weirdfadeto** (*s*,*t*:palette; *d*:integer);

Purpose                  Cross-fade between two palettes using integer RGB matching

Parameters            *s*              Source palette

*t*               Target palette

*steps*       Cross-fade duration

Return                    -

Notes                      Faster than **ia\_fadeto** but may result in slight hue shifts while cross-fading

See also                 **ia\_fadeto**, **ia\_loadpalette**, **ia\_setpalette**, **ia\_getpalette**

function **ia\_visible**(*i*:integer):boolean;

Purpose                  Test for sprite visibility in both axes

Parameters            *i*               Sprite number

Return                    True if sprite is visible on screen

Notes                      Uses bounding box, not actual sprite geometry

See also                 **ia\_visiblex**, **ia\_visibley**

procedure **ia\_center**(*i*,*x*,*y*:integer; *pos*:byte);

Purpose                  Center a sprite around a point

Parameters            *i*               Sprite number

*x,y*           Coordinates of center point

*pos*          Centering method:

2              (*x*,*y*) becomes mid-bottom of sprite

4              (*x*,*y*) becomes mid-left of sprite

5              (*x*,*y*) becomes center of sprite

6              (*x*,*y*) becomes mid-right of sprite

8              (*x*,*y*) becomes mid-top of sprite

Return                    -

Notes                      Hint for centering method: Look at the numeric keypad.  Sprite boundary is

123/456/789 "box".  Centering method corresponds to number on each key.

See also                 -

function **ia\_collide**(*a*,*b*:integer):boolean;

Purpose                  Test for sprite collision

Parameters            *a,b*          Sprite numbers

Return                    True if there is a collision between sprites *a*and *b*

Notes                      Collision can be off-screen

Both sprites must have collision data embedded in their format!

See also                 -

procedure **ia\_chainsprite** (*nr*,*len*,*endloop*:integer);

Purpose                  Chain sprites together

Parameters            *nr*            Start sprite number for chain

*len*          Length of chain

*endloop* Final chain sprite link

Return                    -

Notes                      Sprite will cycle *nr*® *nr+1*® *nr+2*® ... ® *nr+len*® *endloop*

Infinite loops can be created by setting *endloop*=*nr*

See also                 **ia\_unchainsprite**

procedure **ia\_unchainsprite** (*nr*,*len*:integer);

Purpose                  Unchain previously chained sprites

Parameters            *nr*            Start sprite number for chain

*len*          Unchain length

Return                    -

Notes                      -

See also                 **ia\_chainsprite**

function **ia\_gettile**(*x*,*y*:integer):byte;

Purpose                  Get a tile from the scroll area

Parameters            *x,y*           Coordinates to get tile from in pixels

Return                    Tile number under *x,y*

Notes                      *x1,y1* are automatically aligned on a 16x16 grid

See also                 **ia\_puttile**

procedure **ia\_setstatic**;

Purpose                  Set static background (disable scrolling background)

Parameters            -

Return                    -

Notes                      *Tiles* page is not deallocated

See also                 **ia\_setscrolling**

procedure **ia\_setcycletime** (*i*:integer);

Purpose                  Set frame duration

Parameters            *i*               Frame duration in milliseconds

Return                    -

Notes                      Frame rate will be limited to *i*.

Has no effect if frames cannot be displayed as fast as *i*

See also                 -

procedure **ia\_setwindow** (*x1*,*y1*,*x2*,*y2*:integer);

Purpose                  Set animation window

Parameters            *x1,y1*      Coordinates of top-left corner of animation window

*x2,y2*      Coordinates of bottom-right corner of animation window

Return                    -

Notes                      -

See also                 -

### Advanced Commands

function **clock**:longint;

Purpose                  Return the current time

Parameters            -

Return                    Milliseconds elapsed since midnight

Notes                      -

See also                 -

procedure **ia\_error** (*caller*:string; *errornum*:byte; *param*:string);

Purpose                  Error handling routine

Parameters            *caller*     Procedure that generated the error

*errornum* Error number

*param*    Parameter that caused the error

Return                    -

Notes                      Program halts after printing error.

Possible error numbers are.

1              Parameter(s) out of range.

2              File does not exist.

3              Not an UVE file.

4              Wrong file type.

5              Not enough memory.

6              Attempt to dereference nil pointer.

7              No VGA display adapter detected.

8              Scrolling area too large.

9              Tile placed out of scroll area.

See also                 -

function **ia\_detectvga**:boolean;

Purpose                  Detect the presence of a VGA adapter

Parameters            -

Return                    True if VGA present

Notes                      -

See also                 -

procedure **ia\_drawasciiscreen**;

Purpose                  Draw UVE opening text screen

Parameters            -

Return                    -

Notes                      -

See also                 **ia\_uvetext**

procedure **ia\_uvetext** (*caller*, strng, *parameter*: string);

Purpose                  Print out text in UVE standardized format

Parameters            *caller*     Calling procedure

*parameter*Text to print

Return                    -

Notes                      -

See also                 **ia\_drawasciiscreen**

procedure **ia\_waitretrace**;

Purpose                  Wait for VGA vertical retrace signal

Parameters            -

Return                    -

Notes                      Not needed, but included for completeness

See also                 -

procedure **ia\_delspr** (*n*:integer);

Purpose                  Delete a sprite from memory

Parameters            *n*              Sprite number to delete

Return                    -

Notes                      -

See also                 **ia\_loadspr**

function **ia\_searchinwad** (var *fp*:file; *lookingfor*:string):longint;

Purpose                  Position a file pointer to a specified entry in a UVW file

Parameters            *fp*            File handle (must be of type FILE)

Return                    Size of file requested

Notes                      Calls **ia\_error** if entry is not present in UVW

See also                 **ia\_setwadfile**

function **ia\_findclosestcolor** (var *p*:palette; *r*,*g*,*b*:integer):byte;

Purpose                  Find closest color using least squares method

Parameters            *p*              Palette var to search in

*r,g,b*        Desired RGB components

Return                    Index of closest color matching RGB components specified

Notes                      -

See also                 **ia\_makeshadowmap**, **ia\_makeglenzmap**

function **ia\_visiblex**(*i*:integer):boolean;

Purpose                  Test for sprite visibility in x-axis

Parameters            *i*               Sprite number

Return                    True if sprite is visible on screen x-extents

Notes                      Uses bounding box, not actual sprite geometry

See also                 **ia\_visibley**, **ia\_visible**

function **ia\_visibley**(*i*:integer):boolean;

Purpose                  Test for sprite visibility in y-axis

Parameters            *i*               Sprite number

Return                    True if sprite is visible on screen y-extents

Notes                      Uses bounding box, not actual sprite geometry

See also                 **ia\_visiblex**, **ia\_visible**

procedure **ia\_displaysprite** (*n*:integer; *destofs*,*destseg*:word);

Purpose                  Display a sprite

Parameters            *n*              Sprite number

*destofs*Destination offset

*destseg*   Destination segment

Return                    -

Notes                      Performs no clipping

See also                 **ia\_displaysprite\_mapped**, **ia\_displaysprite\_transparent**

procedure **ia\_displaysprite\_mapped** (*n*:integer; *destofs*,*destseg*:word; *m*:byte);

Purpose                  Display a sprite using a map table

Parameters            *n*              Sprite number

*destofs*Destination offset

*destseg*   Destination segment

*m*             Map table index

Return                    -

Notes                      Performs no clipping

See also                 **ia\_displaysprite**, **ia\_displaysprite\_transparent**

procedure **ia\_displaysprite\_transparent** (*n*:integer; *destofs*,*destseg*:word; *m*:byte);

Purpose                  Display a transparent sprite using a map table

Parameters            *n*              Sprite number

*destofs*Destination offset

*destseg*   Destination segment

*m*             Map table index

Return                    -

Notes                      Performs no clipping

See also                 **ia\_displaysprite**, **ia\_displaysprite\_mapped**

procedure **ia\_displaytile** (*n*:byte; *lineofs*,*destseg*:word);

Purpose                  Display a tile

Parameters            *n*              Tile number

*lineofs*    Destination offset

*destseg*   Destination segment

Return                    -

Notes                      Performs no clipping

See also                 **ia\_loadtil**,**ia\_gettile**, **ia\_puttile**

procedure **ia\_doframepart1**;

Purpose                  Execute first part of frame cycle

Parameters            -

Return                    -

Notes                      Copies *background* page onto *hidden* page and/or constructs tiled background

See also                 **ia\_doframepart2**, **ia\_doframepart3**, **ia\_doframe**

procedure **ia\_doframepart2**;

Purpose                  Execute second part of frame cycle

Parameters            -

Return                    -

Notes                      Display all sprites onto *hidden* page

See also                 **ia\_doframepart1**, **ia\_doframepart3**, **ia\_doframe**

procedure **ia\_doframepart3**;

Purpose                  Execute third part of frame cycle

Parameters            -

Return                    -

Notes                      Copy  *hidden* page to *vga* page

See also                 **ia\_doframepart1**, **ia\_doframepart2**, **ia\_doframe**

procedure **ia\_setspritesused** (*i*:integer);

Purpose                  Set number of active sprites

Parameters            *i*               Sprite number

Return                    -

Notes                      Only sprites with number between 1 and *i* will be displayed

See also                 -

procedure **ia\_setclipdepth** (*i*:integer);

Purpose                  Set number of sprites clipped to screen ("in front" of animation window)

Parameters            *i*               Sprite number

Return                    -

Notes                      Sprites with number between 1 and *i* will be clipped to 320x200 screen

Sprites with number between *i+1*and *nmax* will be clipped to animation window

See also                 -

function **ia\_strlength** (*s*:string):word;

Purpose                  Get string length

Parameters            *s*              String to calculate length of

Return                    Length of string in pixels when printed out in the current font attributes

Notes                      -

See also                 **ia\_loadfont**, **ia\_setfontattr**, **ia\_printstr**

procedure **ia\_newpage** (var *p*:pagepointer; var *where*:word);

Purpose                  Allocate a new page

Parameters            -

Return                    *p*              points to the new allocated page

*where*     holds new page segment

Notes                      Calls **ia*\_*error** if there is not enough memory left

See also                 -

procedure **ia\_openfli**(*filename*:string);

Purpose                  Open a FLI file

Parameters            *filename*                FLI file name

Return                    -

Notes                      Calls **ia\_error** if file is cannot be found

See also                 **ia\_setfliparameters**, **ia\_playframe**, **ia**\_**wait4nextframe**, **ia\_closefli**, **ia\_playfli**

procedure **ia\_playframe**;

Purpose                  Play the next frame of a FLI file

Parameters            -

Return                    -

Notes                      -

See also                 **ia\_setfliparameters**, **ia\_openfli**, **ia**\_**wait4nextframe**, **ia\_closefli**, **ia\_playfli**

procedure **ia\_wait4nextframe**;

Purpose                  Wait until current FLI frame time expires

Parameters            -

Return                    -

Notes                      -

See also                 **ia\_setfliparameters**, **ia\_openfli**, **ia\_playframe**, **ia\_closefli**, **ia\_playfli**

procedure **ia\_closefli**;

Purpose                  Close a FLI file

Parameters            -

Return                    -

Notes                      -

See also                 **ia\_setfliparameters**,**ia\_openfli**, **ia\_playframe**, **ia**\_**wait4nextframe**, **ia\_playfli**

procedure **ia\_setfliparameters**(*a*:integer; *b*:word; *c*:boolean);

Purpose                  Set FLI play parameters

Parameters            *a*              FLI playing speed

*b*              FLI loop times

*c*              True if FLI can be interrupted by a keypress

Return                    -

Notes                      Use *a*=-1 to use FLI internal speed

See also                 **ia\_openfli**, **ia\_playframe**, **ia**\_**wait4nextframe**, **ia**\_**closefli**,**ia\_playfli**

# Supporting Utilities

## UVSINFO

UVSINFO is a simple utility that gives information about sprites contained in a single/multiple sprite file (.UVS/.UVL).

## PCX2UVS

PCX2UVS is a utility that converts a PCX file into a sprite (.UVS) file.  It can also optionally save the PCX's palette for use with that sprite.  The PCX's background must be black (color index 0).  UVE32 automatically calculates the bounding box from the PCX image and saves the sprite.  Any part of the sprite that is drawn in black will be completely transparent when displayed on the screen.  A PCX file can only hold a single sprite.  (You can get a far more powerful version of PCX2UVS if you register).

## PCX2UVT

PCX2UVT is a utility that converts a PCX file into a tile (.UVT) file.  The PCX's background must be black (color index 0).  No bounding box is used.  The first non-black pixel found is assumed to be the top-left pixel of a 16x16 tile.  You can have multiple tiles in the PCX.  In such a case, the tiles will all be saved in a single file in the order they were detected (top-to-bottom, left-to-right).

Note:  As no bounding box is used when saving tiles, the top-left pixel of each tile must not be black, so that the start of a tile is properly detected.

## LIBMAKER

LIBMAKER is a powerful utility that allows you to combine multiple files together.  Its most obvious use is to concatenate .UVS or .UVT files into library (.UVL) files.  It cannot be used to create wad files (.UVW).  The files will be concatenated in the order they were selected.

There is a maximum of 100 files that can be simultaneously displayed.  This means that your UVL files can contain at most 100 sprites/tiles.  Workaround:  First split your files into groups of (at most) 100 files, combine them separately, and then combine the resultant UVL files into your final master UVL file.  Hope you got that.

# Known bugs... err.. features

The following list contains all the bugs/limitations I am aware of (but don't intend to fix, at least in the near future).

·         When using a scrolling (tiled) background, the animation window must be at least 16 pixels long in both dimensions, i.e. it must be able to contain at least one full tile.  Tiles are not clipped properly if the animation window is smaller than that.

# UVE32 Frequently Asked Questions

·         *Why is there still only one question in the UVE32 FAQ?*

What can I say?  There haven't been any frequently asked questions.  This can only mean two things: Either UVE32 is flawless, or nobody has bothered downloading it :-)

# UVE mailing list

Starting with v1.40 there is a mailing list which you can join.  You can use the mailing list to communicate with other UVE users world-wide, post problems, comments, suggestions and so on.  To join the mailing list send e-mail to:

**majordomo@lennon.shim.org.sg**

with the words "subscribe uve" in the body of the message (subject is not important).  You should get a confimation back upon joining the list, along with some additional information.

# Where can I get UVE32?

The two primary sites where the lastest version of UVE32 will be uploaded first are:

·         The SimTel archive in the US (ftp to ftp.simtel.net or ftp.cdrom.com) in pub/simtelnet/msdos/turbopas/

·         The X2 archive in Finland (ftp to x2ftp.oulu.fi) in pub/msdos/programming/libs/

Of course, since everybody mirrors everybody else these days, it should soon spread to just about everywhere.  If you cannot access these sites, try getting UVE32 from a nearby mirror site.  At the time of this writing, the official mirroring sites are:

For the SimTel archive:

**Country                Host                                       Directory**

Argentina        ftp.satlink.com             /pub/mirrors/simtelnet

Australia          ftp.bhp.com.au             /pub/simtelnet

Australia          ftp.iniaccess.net.au         /pub/simtelnet

Australia          ftp.tas.gov.au                /pub/simtelnet

Australia          sunsite.anu.edu.au        /pub/pc/simtelnet

Austria            ftp.univie.ac.at              /mirror/simtelnet

Belgium                          ftp.linkline.be                /mirror/simtelnet

Belgium                          ftp.tornado.be              /pub/simtelnet

Bulgaria           ftp.eunet.bg                 /pub/simtelnet

Brazil              ftp.iis.com.br                /pub/simtelnet

Brazil              ftp.unicamp.br            /pub/simtelnet

Canada,Ottawa                ftp.crc.doc.ca               /systems/ibmpc/simtelnet

Canada,Vancvr ftp.direct.ca                  /pub/simtelnet

Chile               sunsite.dcc.uchile.cl         /pub/Mirror/simtelnet

China            ftp.pku.edu.cn              /pub/simtelnet

Czech Republic                  ftp.eunet.cz                 /pub/simtelnet

Czech Republic                  pub.vse.cz                  /pub/simtelnet

Czech Republic                  ftp.zcu.cz                    /pub/simtelnet

Finland            ftp.funet.fi                    /mirrors/ftp.simtel.net/pub/simtelnet

France            ftp.grolier.fr                   /pub/simtelnet

France           ftp.ibp.fr                     /pub/simtelnet

Germany                        ftp.mpi-sb.mpg.de                         /pub/simtelnet

Germany                        ftp.rz.ruhr-uni-bochum.de                 /pub/simtelnet

Germany                        ftp.tu-chemnitz.de        /pub/simtelnet

Germany                        ftp.uni-heidelberg.de        /pub/simtelnet

Germany                        ftp.uni-magdeburg.de                     /pub/mirrors/simtelnet

Germany                        ftp.uni-paderborn.de      /pub/simtelnet

Germany                        ftp.uni-trier.de                /pub/pc/mirrors/simtelnet

Germany                        ftp.rz.uni-wuerzburg.de   /pub/pc/simtelnet

Greece           ftp.ntua.gr                   /pub/pc/simtelnet

Hong Kong                      ftp.cs.cuhk.hk              /pub/simtelnet

Hong Kong                      ftp.hkstar.com             /pub/simtelnet

Hong Kong                      sunsite.ust.hk                /pub/simtelnet

Israel               ftp.huji.ac.il                  /pub/simtelnet

Italy               cis.utovrm.it                 /simtelnet

Italy               ftp.flashnet.it                /pub/simtelnet

Italy               ftp.unina.it                   /pub/simtelnet

Italy               mcftp.mclink.it             /pub/simtelnet

Japan            ftp.iij.ad.jp                   /pub/simtelnet

Japan            ftp.riken.go.jp               /pub/simtelnet

Japan            ftp.saitama-u.ac.jp         /pub/simtelnet

Japan            ftp.u-aizu.ac.jp              /pub/PC/simtelnet

Japan            ring.aist.go.jp                 /pub/simtelnet

Japan            ring.asahi-net.or.jp          /pub/simtelnet

Latvia             ftp.lanet.lv                   /pub/mirror/simtelnet

Malaysia                         ftp.jaring.my                /pub/simtelnet

Malaysia                         ftp.mimos.my                             /pub/simtelnet

Mexico                           ftp.gdl.iteso.mx             /pub/simtelnet

Netherlands                      ftp.euro.net                  /d5/simtelnet

Netherlands                      ftp.nic.surfnet.nl             /mirror-archive/software/simtelnet

New Zealand                    ftp.vuw.ac.nz               /pub/simtelnet

Norway                          ftp.bitcon.no                /pub/simtelnet

Poland           ftp.cyf-kr.edu.pl             /pub/mirror/Simtel.Net

Poland           ftp.icm.edu.pl               /pub/simtelnet

Poland           ftp.man.poznan.pl                        /pub/simtelnet

Portugal             ftp.ip.pt                     /pub/simtelnet

Portugal           ftp.ua.pt                     /pub/simtelnet

Romania                        ftp.sorostm.ro               /pub/simtelnet

Singapore        ftp.nus.sg                    /pub/simtelnet

Slovakia         ftp.uakom.sk                              /pub/simtelnet

Slovenia         ftp.arnes.si                   /software/simtelnet

South Africa     ftp.is.co.za                   /pub/simtelnet

South Africa     ftp.sun.ac.za                /pub/simtelnet

South Korea     ftp.nuri.net                   /pub/simtelnet

South Korea                     ftp.sogang.ac.kr            /pub/simtelnet

South Korea                     sunsite.snu.ac.kr            /pub/simtelnet

Spain              ftp.rediris.es                  /mirror/simtelnet

Sweden                           ftp.sunet.se                  /pub/simtelnet

Switzerland      ftp.switch.ch                /mirror/simtelnet

Taiwan                           ftp.ncu.edu.tw              /Packages/simtelnet

Taiwan                           nctuccca.edu.tw                           /mirror/simtelnet

Thailand         ftp.nectec.or.th              /pub/mirrors/simtelnet

UK, Edinburgh                   emwac.ed.ac.uk                           /mirrors/simtelnet

UK, London                     ftp.demon.co.uk                           /pub/simtelnet

UK, Lancaster                   micros.hensa.ac.uk                        /pub/simtelnet

UK, London                     sunsite.doc.ic.ac.uk         /packages/simtelnet

US, California   ftp.cdrom.com                            /pub/simtelnet

US, California   ftp.digital.com              /pub/micro/pc/simtelnet

US, Illinois         uiarchive.cso.uiuc.edu    /pub/systems/pc/simtelnet

US, Mass.        ftp.bu.edu                   /pub/mirrors/simtelnet

US, Michigan                    oak.oakland.edu                          /pub/simtelnet

US, New York                   ftp.rge.com                 /pub/systems/simtelnet

US, Oklahoma                  ftp.ou.edu                   /pub/simtelnet

US, Oregon                       ftp.orst.edu                   /pub/simtelnet

US, Utah         ftp.cyber-naut.com                        /pub/simtelnet

US, Virginia       mirrors.aol.com             /pub/simtelnet

For the X2 archive:

Site: ftp.ibp.fr (France)

Path: /pub/pc/x2ftp/

Mirror: books,msdos

Update: 0330 GMT

Site: ftp.rz.uni-karlsruhe.de (Germany)

Path: /pub/programming/mirror.x2ftp/

Mirror: books,msdos,unix

Update: 0200 GMT

Site: ftp.infomagic.com (USA)

Path: /pub/mirrors/x2ftp/

Mirror: amiga,books,console,msdos,standards

Update: 0400 GMT

Site: illusion.shiny.it (Italy)

Path: /pub/x2ftp/

Mirror: msdos

Update: 0500 GMT

Site: mirrors.aol.com (USA)

Path: /pub/x2ftp

Mirror: books,console,msdos

Update: 2330 GMT

Site: ftp.ee.techpta.ac.za (168.172.8.5) (South Africa)

Path: /pub/mirrors/x2ftp/

Mirror:

Update: 2300 GMT

Site: ftp.lanet.lv (Latvia)

Path: /pub/mirror/x2ftp/

Mirror: books,msdos

Update: 0130 GMT

Site: http://www2.cp.eng.chula.ac.th/mirror1/x2ftp

Mirror: msdos

Update: 2100 GMT

Freq.: weekly (Friday)

Admin: ftpadm@cpu.cp.eng.chula.ac.th

# Contacting InterAction software

You can contact me for any reason, whether it's to ask for registration information, to ask if/how you can do something in UVE32, to report a bug, or just to say what you like/don't like about UVE32.  Alternatively, you can join the UVE mailing list (more information in the relevant section).

When writing in to report a bug or ask something about a command, please take the time to read through the manual.  There is a good chance the answer you are looking for is already there.  Also, check the FAQ for answers to frequently asked questions.  When you writing in with a question, please include in your mail information about the version of UVE32 you are using.

Okay, by far the best way to contact me is through e-mail.  My address is:

**cbp@doc.ic.ac.uk**

Note that this address is only valid until the 1st of July, 1998.  Furthermore, avoid sending mail to that address during the Christmas, Easter, and Summer holidays as I will not be checking my mail regularly during those times.  You can alternatively send mail to the following address:

**robin@hol.net**

It's probably A Good Idea to send your mail to both addresses to minimize latency time (I love it when I use jargon).  Some e-mail bounces, so if you haven't heard from me in 15 days, send your mail again, perhaps including more complete or alternative reply addresses.

If you have no access to the Internet, You can use conventional surface mail, although I can't guarantee how long it's going to take before you get an answer.  You can write to:

**Constantine Prouskas**

**4 Adrianoupoleos street**

**GR 156-69 Papagou**

**Athens, GREECE**

# Registering

UVE32 is shareware.  It is not free.  If you use UVE32 for 21 days and wish to continue using it, you must register it.  Read the License Agreement for more information on what you are and are not allowed to do.  By registering you are acknowledging all he work that has gone behind this product and supporting further development.

By registering, you get:

·         My eternal gratitude :-)

·         The latest version of UVE32 for Turbo Pascal 6.0 & 7.0 on disk, plus the protected mode version for Borland Pascal 7.0.

·         Unlimited mail/e-mail support (including hot tips on how it's possible to have a 2-player split screen in UVE32).

·         The complete documentation in Rich Text Format (.RTF), complete with advanced formatting and tables.

·         Registered versions of all the supporting utilities, including UVSINFO, PCX2UVS, PCX2UVT, LIBMAKER.

·         An advanced, powerful version of PCX2UVS that allows multiple sprites per PCX and complete control over the save region.

·         WADMAKER:  An extra utility that can create .UVW files.

·         WADVIEW:  An extra utility that shows the contents of .UVW files.

·         FLI2UVL:  An extra utility that directly creates a UVL file from a FLI file.

·         \*NEW!\* UVE\_KEY: A unit to handle multiple keypresses.  An absolute must for games.

Registration is US$25.  There is a 20% discount (US$20) to any cheque or cash orders. The latest version available at the time of registration will be sent to you on a HD floppy (default is 3.5", specify if you want 5.25") via first class mail.

Starting with v1.40, it is now possible to register using your credit card.  Since this has made things a bit more complicated, I have split up the registration to credit card and non-credit card orders.

## Credit card orders

For your convenience, I have contacted another company, NorthStar solutions, to process any orders you may wish to place with your Visa, MasterCard or Discover card.  NorthStar Solutions can be easily contacted for orders only via any of the following methods:

·         PHONE ORDERS

Available 10am-8pm, EST, Monday through Saturday

1-800-699-6395 (Calls from the U.S. only.)

1-803-699-6395 (Calls from outside the U.S.)

·         FAX ORDERS

1-803-699-5465 (Available 24 hours.  International and business orders encouraged.)

·         INTERNET ORDERS

Simply fill out the online order form at http://ourworld.compuserve.com/homepages/starmail

·         E-MAIL ORDERS

You can send your order via e-mail to:

America Online: STARMAIL

CompuServe: 71561,2751

Internet: 71561.2751@compuserve.com

Please provide (or be prepared to provide) the following information when ordering:

·         The program you are registering (Ultra VGA Engine 32).  You might find it easier to refer to UVE32 by using its product ID, which is #1126.

·         Your mailing address.

·         Your Visa, MasterCard or Discover card number and its expiration date.

·         Your drive type (if other than 3.5").

·         Your e-mail address (so that NorthStar Solutions can send you confirmation of your order).

IMPORTANT!

Please note that NorthStar Solutions only handles credit card orders.  They will not be able to offer any assistance or technical support with any problems you may have with UVE32.  Please refer any such problems to me directly.

Feel free to e-mail me as well, notifying me that you placed an order with NorthStar Solutions if you want to speed up the sending out of the disk.

## Other (non-credit card) orders

Apart from using a credit card, you can also register by the following alternative methods:

·         Cheque.  Must be in U.S. Dollars, British Pounds or Greek Drachmas and made payable to "Constantine Prouskas".

·         Cash.  Again, must be U.S. Dollars, British Pounds or Greek Drachmas.  For other currencies, visit your local bank or travel exchange.  You should be able to convert to one of the above currencies using international exchange rates.

·         Direct deposit in a bank account (U.S., U.K. or Greece only).

Since addresses, bank accounts and the like are subject to change, however, it's best if you contact me at the above address first (see the "Contacting InterAction software" section).  Apart from notifying me that you want to register, it is possible to work out the payment method that is most convenient on a case-by-case basis (even using a method not described above).  Additionally,  I can arrange sending out the registered version via e-mail, if you so wish.

# Epilogue

This, as they say, is it.  You can take it from here.  I've supplied the tools, you supply the inspiration.

One final request:  If you ever use UVE32 to write any sort of application (especially what it was meant for, games), I ask that you send me a piece of mail saying what it is and where I can get it.  It's your way of letting me know that all the hours of hard work that have gone into UVE32 have really paid off.

Go forth and make some magic.