
svgalib v1.06 (with alpha ATI mach32 driver)

0.  Introduction
1.  Installation
2.  Overview of supported SVGA chipsets and modes
3.  Description of svgalib functions additional to VGAlib v1.2
4.  How to use svgalib
5.  Structure of chipset driver modules
6.  Changes (see file CHANGES)
7.  Known bugs
8.  Goals
9.  References



0.  Introduction

This is a low level graphics library for Linux, based on VGAlib 1.2 by
Tommy Frandsen. VGAlib supported a number of standard VGA graphics modes, as
well as Tseng ET4000 high resolution 256-color modes. I added support for my
Cirrus 542x based card, including 15/16/24 bit color modes, and merged in the
Trident code from Toomas Losin's tvgalib. It also provides ET4000
hicolor/truecolor DAC support. There's also an alpha ATI mach32 driver
by Michael Weller.

It supports transparent virtual console switching, that is, you can switch
consoles to and from text and graphics mode consoles using alt-[function
key]. Also, svgalib corrects most of VGAlib's textmode corruption behaviour
by catching SIGSEGV, SIGFPE and SIGILL, and ensuring that a program is running
in the currently visible virtual console before setting a graphics mode.

When the library is first used by a program at run-time, the chipset is
detected and the appropriate driver is used. This means that a graphics
program will work on any card that is supported by svgalib, if the mode it
uses is supported by the chipset driver for that card. The library is
upwardly compatible with VGAlib.

The set of drawing functions provided by svgalib itself is limited (unchanged
from VGAlib) and unoptimized; you can however use vga_setpage and graph_mem
(which points to the 64K VGA framebuffer) in a program or graphics library.
A fast external framebuffer graphics library for linear and banked 1, 2, 3
and 4 bytes per pixel modes is included (it also indirectly supports planar
VGA modes). There's a README in the gl/ directory.

One obvious application of the library is a picture viewer. I have made a
simple GIF/JPEG viewer that also supports hicolor/truecolor; it should be
available as spicXX.tar.z (sunsite.unc.edu, /pub/Linux/apps/graphics).

I have added a simple VGA textmode font restoration utility (restorefont) 
which may help if you suffer from XFree86 textmode font corruption. It can
also be used to change the textmode font. It's in the utils/ directory,
along with a README and some other textmode utilities: restoretextmode (which
saves/restores textmode registers), restorepalette, and the script textmode.
If you run the savetextmode script to save textmode information to /tmp,
you'll be able to restore textmode by running the textmode script.

If you have an ET4000 card, you should read the README in the et4000/
directory. You will probably want to replace the ET4000 registers.

Directories:
.		svgalib sources.
demos/		Demo and test programs.
utils/		Textmode/font utilities.
gl/		External framebuffer graphics library sources, and docs.
support/	DOS-based utility for dumping VGA registers.
et4000/		Notes, utilities and sample registers for ET4000.
mouse/		Source for mouse functions.
jump/		Configuration files for building DLL shared library.
sharedlib/	Shared library image and stubs.

I welcome any questions, comments, suggestions, bug-reports, etc.

Much of the source code is detrimental to your health, don't look at it.
Only if you are adequately prepared. Do write amazing multi-player
networked 3D lightsource-shaded real-time VGA virtual reality simulations.

Harm Hanemaayer
hhanemaa@cs.ruu.nl



1. Installation

Running 'make install' as root should take care of proper installation.
Shared library stubs and images are included in the distribution. Edit the
Makefile to change installation paths and to select the parts that should be
installed, and edit libvga.config to set the monitor and mouse type.

If things go wrong, make sure that you have properly installed a recent libc 
(i.e. deleted libgcc.(s)a), and that ld.so is up to date.

If you have an ET4000 card, read the et4000/README and copy the appropriate
register file to et4000.regs. Remember to set the DAC type.

The default behaviour is the following:

Shared libraries are installed in /lib and /usr/local/lib, header files
in /usr/local/include (any old header files in /usr/include are removed).

The et4000 registers (et4000.regs) are installed as
/usr/local/lib/libvga.et4000, but only if this file does not exit yet.
The same goes for the configuration file, libvga.config.

Textmode utilities are installed in /usr/local/bin. These are restorefont,
runx, restorepalette, dumpreg, restoretextmode, textmode, savetextmode,
and fix132x43.

If you change the Makefile to install the static libraries, static libraries
are compiled, and installed in /usr/local/include. Note that you do not need
to do this; the shared library is enough.

If you now run 'make', the demo programs are created in the demos/
directory.

You can remove previously installed files (not the et4000 registers and
config file) with 'make uninstall'.

Note that if you change and recompile the (static) library and install it
(you can use 'make installstaticlib installheaders' for this), programs may
still get linked to the (old) shared library version. Try temporarily
removing the stubs in /usr/local/lib, or specifying libvga.a on the
commandline instead of -lvga.



2.  Overview of supported SVGA chipsets and modes

Supported chipsets:

	VGA and compatibles

		320x200x256, and the series of 16-color and non-standard
		planar 256 color modes supported by VGAlib, as well as
		720x348x2.

	Cirrus Logic GD542x

		640x480x256, 800x600x256, 1024x768x256, 640x480x32K,
		640x480x64K, 800x600x32K, 800x600x64K, 1024x768x32K,
		1024x768x64K, 640x480x16M, 320x200x32K, 320x200x64K,
		320x200x16M. The last mode has a logical scanline width
		of 960 bytes, but the VESA BIOS uses 1024. Also,
		800x600x16M at 50 Hz; and 800x600x16, 1024x768x16,
		1280x1024x16. Some bitblt functions are supported.

		The way the second Mb of memory is enabled on 2Mb cards
		is suspect (dependent on DRAM configuration); please
		report any problems with 2Mb cards.

		I would be very interested to hear about anyone with a
		543x chip.

	Tseng ET4000/ET4000W32(i/p)

		Derived from VGAlib; not the same register values.
		ET4000 register values are not compatible; see et4000/README.
		Make sure the colors are right in hicolor mode; the vgatest
		program should draw the same color bars for 256 and hicolor
		modes (the DAC type is defined in et4000.regs or the dynamic
		registers file).
		ET4000/W32 based cards usually have an AT&T or Sierra 
		15025/6 DAC.
		If the high resolution modes don't work, you can try
		dumping the registers in DOS using the program in the
		et4000 directory and putting them in a file
		(/usr/local/lib/libvga.et4000 is parsed at runtime if DYNAMIC
		is defined in config.h).

		640x480x256, 800x600x256, 1024x768x256,
		640x480x32K, 800x600x32K, 640x480x16M, etc.

		Reports of ET4000/W32i/p functionality are welcome.

	Trident TVGA 8900C/9000 (and possibly also 8800CS/8900A/B)

		Derived from tvgalib by Toomas Losin.

		640x480x256, 800x600x256, 1024x768x256 (I and NI)
		Might be useful to add 16-color modes (for those equipped
		with a 512K TVGA9000).

	Oak Technologies OTI-037/67/77

		May work if somebody provides the register dumps (especially
		the extended registers) using XFree86 v2.0 (see	Changes)
		(worked for 640x480x256).

		640x480x256 for now.

	ATI Mach32

		The alpha driver by Michael Weller supports all BIOS-defined
		modes. However, non-Type 2 DAC's are untested. Check out
		README.mach32 (and README.config). Do send feedback.


3.  Additional VGAlib functions

	For vgagl, see gl/README. The mouse and keyboard interfaces are
	"documented" in their headerfiles.

	vga_init()
		Initialize library; detects chipset and gives up supervisor
		rights. Recommended first line of any program that uses
		svgalib; vga_setchipset can be used before it to avoid
		detection.

	vga_modeinfo *vga_getmodeinfo( int mode )
		Returns pointer to mode information structure for a mode.
		width			Width of mode in pixels.
		height			Height of mode.
		bytesperpixel		Bytes per pixel (framebuffer-wise).
					This is 1, 2 or 3, and 0 for planar
					VGA modes.
		linewidth		Logical scanline width in bytes.
		colors			2, 16, 256, 32768, 65536 or 16M
		maxlogicalwidth 	Maximum logical scanline width (bytes).
		startaddressrange 	Mask of changeable bits of start
					address (in pixels).
		maxpixels		Maximum number of pixels that will
					fit in a logical screen (depends on
					video memory).
		haveblit		Indicates whether bitblit functions
					are available.
					Bit 0: Bitblit
					Bit 1: Fillblit
					Bit 2: Imageblit
		flags			Miscellaneous flags.
					Bit 0: Setreadpage/setwritepage
					       available.
					Bit 1: Mode is interlaced.
					Bit 2: Mode is mode-X like (planar
					       256 colors).
					Bit 3: Dynamically loaded mode.
					Bit 4: Can set to linear addressing.
					Bit 5: Linear addressing enabled.
					Bit 6: The following fields in this
					       information structure are set:

		chiptype		the chiptype that was detected/set.
		memory			memory available on the card in KB
		linewidth_unit		use only a multiple of this value for
					set_logicalwidth or set_displaystart
					to ensure graceful alignment of lines
					onto the vga memory in this mode.
		linear_aperture		ptr to a mmaped secondary linear
					framebuffer (NULL if unavailable)
		aperture_size		size of framebuffer in KB. 0 if
					unavailable.
		set_aperture_page	a function taking an int as parameter
					to select a page in the framebuffer if
					aperture_size<memory.
		extensions		pointer to additional info(contents of
					eeprom for mach32 driver.)

	int vga_getcurrentmode()
		Returns the current mode.

	int vga_getdefaultmode()
		Returns the default graphics mode number from the
		GSVGAMODE environment variable; -1 if undefined. The
		environment variable can either be a mode number or a mode
		name.

	int vga_getcurrentchipset()
		Returns the current SVGA chipset.

	void vga_setmousesupport( int stat )
		Set mouse support; 0 disabled (default), 1 enabled. If
		enabled, the mouse is set up for screen resolution after a
		mode set. You can use the function to set up the mouse in
		vgamouse.h instead for more flexibility.

	void vga_runinbackground( int stat )
		Enable/disable background running of a graphics program
		(1 = enable). Normally, the program is suspended while
		not in the current virtual console. A program can only
		safely run in the background if it doesn't do any video
		access during this time.

	int vga_oktowrite()
		Indicates whether the program is in the console currently
		visible on the screen, that is, whether it is OK to write
		to video memory (if running in the background has been allowed
		with the function above). Note that this is not entirely
		safe, since a console switch interrupt may occur during a
		video operation. [best to avoid this function]

	int vga_getkey()
		Read a character from the keyboard without waiting; returns
		-1 if no key pressed.

	void vga_lockvc()
		Disables virtual console switching for safety. Recommended
		when doing register I/O or low-level device handling. Used
		by mouse functions.

	void vga_unlockvc()
		Re-enables virtual console switching.

	void vga_setpage( int page )
		Set 64K SVGA page number.

	unsigned char *graph_mem;
		Pointer to 64K VGA frame buffer window. Can be used by
		graphics library on top of VGAlib.

	unsigned char *vga_getgraphmem()
		Returns graph_mem.

	void vga_waitretrace();
		Wait for vertical retrace. Use to synchronize animation with
		monitor refresh.

	int vga_claimvideomemory( int m ) {
		Declare the amount of video memory in bytes that is to
		be saved when temporarily switching to textmode. Returns
		nonzero if the amount is not available. Defaults to one
		screen when a mode is set. Use this if you are using more
		than one screen of video memory.

	void vga_setchipset( int chipset )
		Force chipset (when chipset detection fails).
		vga_setchipset(VGA) can be useful if the chipset specific
		stuff or the SVGA detection stuff gives problems.

	void vga_setchipsetandfeatures( int chipset, int par1, int par2 )
		Force chipset, and optional parameters like the exact
		chipset type and the amount of video memory installed.
		[Only for debugging.]

	void vga_setlogicalwidth( int l )
		Set the logical scanline width to l bytes. Must be a
		multiple of 8. Only changes the VGA register, drawing
		functions don't take it into account.

	void vga_setdisplaystart( int a )
		Set the display start address to a, where the address is the
		number of pixels offset from the start of video memory,
		except for hicolor/truecolor modes, which use a unit of
		1 byte. Can be used for page-flipping and virtual desktop
		scrolling. May not work properly for 16 color modes.

	void vga_setrgbcolor( int r, int g, int b )
		Set the current color to RGB values r, g, and b, each in
		the range 0-255. Does not make sense in 256-color modes.

	void vga_setmodeX()
		Try to enable Mode X-like memory organization (only for
		256 color modes using up to 256K of memory like 320x200x256
		and 640x400x256; 320x240x256 etc. are Mode X-like by default).

	void vga_copytoplanar256( unsigned char *virtual, int pitch,
	int voffset, int vpitch, int w, int h )
		Copy part of linear virtual screen in system memory to Mode
		X video memory. pitch is the logical width of the virtual
		screen; voffset is the address offset into video memory;
		vpitch is the logical scanline length of the screen; (w, h)
		is the size of the area to copy in pixels (width must be
		multiple of 4).

	void vga_copytoplanar16( unsigned char *virtual, int pitch,
	int voffset, int vpitch, int w, int h )
		Similar function for 16 color modes (untested); assumes
		pixels stored in consecutive bytes ranging from 0 to 15 in
		the virtuals screen.

	void vga_setlinearaddressing()
		Switch to linear addressing mode. Only valid on Cirrus,
		with less than 16Mb of memory (maps at 14Mb).
		vga_getgraphmem returns the linear framebuffer address
		(fixed at 0x40000000; letting the kernel give the address
		wastes 2Mb). vga_ drawing functions are not supported;
		vgagl does support it (gl_setcontextvga).

	void vga_safety_fork( void (*shutdown_routine(void))
		Calling this at the start of a program results in a better
		chance of textmode being restored in case of a crash.

	A note about vga_drawscansegment:
	In hicolor/truecolor modes, the lenght must be given in bytes,
	not pixels.

	The following functions are only defined if the corresponding flag
	in the haveblit field of the mode info structure is set. They are
	not meant as graphics primitives, but more as an interface to the
	blitter in the Cirrus 5426. Note: the maximum height is 1024 for
	the Cirrus routines.

	void vga_bitblt( int srcaddr, int destaddr, int w, int h,
	int pitch )
		Bitblit (copy rectangular area in video memory), addresses
		are offsets into video memory (up to 2M). The pitch is the
		logical width of the screen.

	void vga_fillblt( int destaddr, int w, int h, int pitch, int color )
		Fill a rectangular area in video memory with a single color.

	void vga_imageblt( void *srcaddr, int destaddr, int w, int h, int
	pitch )
		Write a rectangular bitmap from system memory to video
		memory.



4.  How to use svgalib (and vgagl)

The function vga_getdefaultmode() checks the environment variable GSVGAMODE
for a default mode, and returns the corresponding mode number. The
environment string can either be a mode number (compatible with (S)VGAlib
Ghostscript), or a mode name as in (G640x480x2, G640x480x16, G640x480x256,
G640x480x32K, G640x480x64K, G640x480x16M). As an example, to set the default
graphics mode to 640x480, 256 colors, use: export GSVGAMODE=G640x480x256
on the bash command line. If a program needs just a linear VGA/SVGA resolution
(as required by vgagl), only modes where bytesperpixel in the vga_modeinfo
structure is greater or equal to 1 should be accepted (this is 0 for tweaked
planar 256-color VGA modes).

Use vga_setmode(graphicsmode) to set a graphics mode. Use vga_setmode(TEXT) to
restore textmode before program exit.

Programs that use svgalib must include vga.h; if they also use the external
graphics library vgagl, vgagl.h must also be included. Linking must be done
with -lvga (and -lvgagl *before* -lvga, if vgagl is used). You can save binary
space by removing the chipset drivers in config.h if you only use standard VGA
(only for static binaries; better link with the shared library).

Functions in the vgagl library have the prefix "gl_". To initialize vgagl,
the graphics context must be set. Example:

	vga_setmode(G320x200x256);
	gl_setcontextvga(G320x200x256);

In this example, the context is set to the physical screen. The context can
be saved (only the screen type, not the contents) into a variable, e.g.

	GraphicsContext physicalscreen;

	gl_getcontext(&physicalscreen).

To define a virtual screen in system memory, use gl_setcontextvgavirtual:

	gl_setcontextvgavirtual(G320x200x256)

which allocates space for a screen identical to 320x200x256 graphics mode,
and makes this virtual screen the current graphics context.

The virtual screen can now be copied to the physical screen as follows:

	gl_copyscreen(&physicalscreen);



5.  Structure of the chipset drivers

	Note: This may not be entirely up to date with Hartmut's changes.

	The chipset specific registers saving function (saveregs) is only
	used directly to save the textmode registers at initialization.

	The chipset specific registers restoring function (setregs) is only
	used directly to return to textmode, and when setting a VGA mode
	after an SVGA mode.

	The registers for each mode are stored like the ET4000 modes in
	VGAlib 1.2, i.e. the extended registers at the end. The following
	functions must be provided in a driver:

	saveregs( unsigned char regs[] )
		Saves the chipset-specific registers in regs, starting at
		array index EXT (after the VGA registers).

	setregs( unsigned char regs[] )
		Sets the chipset-specific registers stored in regs from
		index EXT.

	modeavailable( int mode )
		Returns nonzero if mode is available (should check video
		memory).

	getmodeinfo( vga_modeinfo *modeinfo )
		Fills in chipset specific field of mode information
		structure: maxlogicalwidth, startaddressrange (mask of
		significant bits), and maxpixels (video memory divided by
		the number of bytes per pixel). haveblit indicates whether
		bitblt functions are available.
		Note: providing extended info and an aperture with size
		>= memory and setting bits 4 and 6 in flags will
		automatically enable linear addressing support. 
		

	setmode( int mode, int previous_mode )
		Sets all registers for a mode; returns nonzero if mode not
		available. __vga_setregs can be called to set the VGA
		registers.

	unlock()
		Unlocks chipset-specific registers.

	lock()
		Lock (protect) chipset-specific registers. Currently not
		called.

	test()
		Identify chipset; initialize (check memory and type) and
		return nonzero if detected.

	setpage( int page )
		Set 64K page number to be mapped at 0xa0000.

	init( int force, int par1, ... )
		Initialize memory and type; called by test. If force is 1,
		the chiptype or the amount of memory can be forced (this
		is pretty useless).

	The following functions are not required; they provide for things
	like page flipping and hardware scrolling virtual desktops.

	setdisplaystart( int addresss )
		Sets the display start address in video memory in pixels.

	setlogicalwidth( int width )
		Sets the logical scanline length in bytes. Usually a
		multiple of 8.

	The function getchipset() in vga.c must call the test routine for
	the chipset. The chipsetfunctionslist must be have a pointer
	to the chipsetfunctions table for the chipset (which is the only
	global symbol in a chipset driver). Also, vga.h contains a magic
	number for each chipset. Also driver_names[] in vga.c has to
	contain a name for each driver at the correct position.



6.  Changes

See the file CHANGES.



7.  Bugs

	Using a 132 column textmode may cause graphics modes to fail. Try
	using something like 80x28.

	The console switching doesn't preserve some registers that may be
	used to draw in planar VGA modes.

	Wild console switching can cause the text screen to be corrupted,
	especially when switching between two graphics consoles.

	On ET4000, having run XFree86 may cause high resolution modes to
	fail (this is more XFree86's fault).

	The Trident probing routine in the XFree86 server may cause standard
	VGA modes to fail after exiting X on a Cirrus. Try putting a 'Chipset'
	line in your Xconfig to avoid the Trident probe, or use the link kit
	to build a server without the Trident driver. Saving and restoring
	the textmode registers with savetextmode/textmode (restoretextmode)
	should also work. [Note: svgalib now resets the particular extended
	register, but only if the Cirrus driver is used (i.e. the chipset
	is not forced to VGA)] [This is fixed in XFree86 v2.1]

	Some Paradise VGA cards may not work even in standard VGA modes. Can
	anyone confirm this?

	Sometimes the console input shows strange behaviour (e.g. the bash
	history function doesn't work) after running a graphics program.

	Also, piping data into a graphics program has problems.

	The tseng3 program doesn't recognize any modes on some ET4000 cards.
	Also ET4000 cards with a Acumos/Cirrus DAC may only work correctly
	in 64K color mode.


8.  Goals

	I think the ability to use a VGA/SVGA graphics resolution in one
	virtual	console, and being able to switch to any other virtual console
	and back makes a fairly useful implementation of graphics modes in
	the Linux console.

	Programs that use svgalib must be setuid root. I don't know how
	desirable it is to have this changed; direct port access can hardly
	be done without. Root priviledges can now be given up right after
	initialization. I noticed some unimplemented stuff in the kernel
	header files that may be useful, although doing all register I/O via
	the kernel would incur a significant context-switching overhead.

	It is important that textmode is restored properly and reliably; it
	is fairly reliable at the moment, but fast console switching back
	and forth between two consoles running graphics can give problems.
	Wild virtual console switching also sometimes corrupts the contents
	of the textmode screen buffer (not the textmode registers or font).

	Currently, programs that are in graphics mode are suspended while
	not in the current virtual console. Would it be a good idea to let
	them run in the background, virtualizing framebuffer actions (this
	should not be too hard for linear banked SVGA modes)? It would be
	nice to have, say, a raytracer with a real-time display run in the
	background (although just using a seperate real-time viewing
	program is much more elegant).

	Anyone wanting to rewrite it all in a cleaner way (something with
	loadable kernel modules shouldn't hurt performance with linear
	framebuffer/vgagl type applications) is encouraged.

	Also, if anyone feels really strongly about a low-resource and
	truecolor supporting graphical window environment with cut-and-paste,
	I believe it would be surprisingly little work to come up with a
	simple but very useful client-server system with shmem, the most
	useful applications being fairly trivial to write (e.g. shell
	window,	bitmap viewer).	And many X apps would port trivially. Maybe
	something for a university project (hint, hint)?


9.  References

	VGAlib v1.2: tsx-11.mit.edu, directory pub/linux/sources/libs:
	vgalib12.tar.Z
	tvgalib-1.0.tar.Z is in the same directory.
	SLS has long been distributing an old version of VGAlib.
	svgalibXX.tgz may be found on sunsite.unc.edu, /pub/Linux/libs,
	spic in apps/graphics/viewers. Also in that directory is seejpeg,
	which shows the picture as it is being built up.
	In the directory is also a svgalib port of the Berkeley MPEG decoder
	(mpeg_play), mpeg-linux.tgz. 
	Also on sunsite is egalib, which is a VGAlib compatible library
	for EGA equipped systems.

	zgv v1.2 is a GIF/JPEG viewer with a nice file selector that uses
	VGAlib (svgalib is compatible with vgalib), on tsx-11.mit.edu,
	/pub/linux/[binaries|sources]. 

	In the info directory of the SIMTEL MSDOS collection, there is a
	package called vgadoc2 which is a collection of VGA/SVGA register
	information.

	The XFree86 driver sources distributed with the link-kit may be
	helpful.

	LIBGRX, the extensive framebuffer library by Csaba Biegl distributed
	with DJGPP, will probably be ported to Linux. Contact Hartmut Schirmer
	(phc27@rz.uni-kiel.d400.de, subject prefix "HARTMUT:").

	The vgalib ghostscript device driver sources can be found on
	sunsite, /pub/Linux/apps/graphics.
	Ghostscript patches from Slackware: ftp.cdrom.com, /pub/linux/misc.
	gnuplot patches are on sunsite.

	There are nice VGA arcade games that use svgalib; at least
	B*lderdash and Sasteroids, which is very impressive but the initial
	distribution was tricky to compile.
