2 -----------------------------------------------------------------------------
\r
4 ********* XLIB - Mode X graphics library ****************
\r
5 ********* ****************
\r
6 ********* Written By Themie Gouthas ****************
\r
7 ********* ****************
\r
8 ********* egg@dstos3.dsto.gov.au ****************
\r
9 ********* teg@bart.dsto.gov.au ****************
\r
11 Some of the code in this library has been contributed by :
\r
13 Matthew MacKenzie - matm@eng.umd.edu
\r
15 and others. See individual modules.
\r
17 I informally reserve all rights to the code in XLIB
\r
18 Rights to contributed code is also assumed to be reserved by
\r
19 the original authors.
\r
20 -----------------------------------------------------------------------------
\r
21 MODULE XCLIPPBM note: VERY SIMILAR to XPBMCLIP
\r
22 This module implements blits of clipped planar bitmaps. Blits are
\r
23 clipped to pixels, both horizontally. This makes the unmasked blit
\r
24 function here slightly slower than the equivalent functions in the
\r
26 --------------------------------------------------------------------------
\r
29 by Matthew MacKenzie
\r
31 The XCLIPPBM module contains clipping versions of two of the three routines
\r
32 in the XPBITMAP module:
\r
33 o x_clip_pbm transfers a planar bitmap to the screen, clipping off any
\r
34 part outside a bounding box.
\r
35 o x_clip_masked_pbm does the same thing, but transfers only nonzero
\r
38 The planar bitmap format is described elsewhere. Here we will look at
\r
39 the clipping itself, since it is the only distinguishing feature of this
\r
41 The bounding box is made up of four integers, TopBound, BottomBound,
\r
42 LeftBound, and RightBound. Unlike most global variables in Xlib, these are
\r
43 meant to be written to. In fact, they start out uninitialized. Be sure to
\r
44 set them before you try plotting any clipped bitmaps.
\r
45 Note that these are not the same variables which are used in the other
\r
46 clipping modules in Xlib. This is because the two systems are incompatible:
\r
47 the other modules clip horizontally to columns while this one clips to
\r
48 pixels. As you might have guessed, those functions and these were developed
\r
49 in different hemispheres of the planet...
\r
50 If it's any consolation, this does give you two independent
\r
51 bounding boxes to futz with, should the mood visit you.
\r
52 Bitmaps cannot go outside the perimeter of the bounding box, but they
\r
53 can overlap it. If TopBound equals BottomBound, for example, a horizontal
\r
54 slice of a bitmap may still be plotted. It is safe to turn the box "inside
\r
55 out" to make sure nothing will be plotted -- this is the first thing each
\r
57 To plot a bitmap, minus its zero pixels, minus anything outside the
\r
60 x_clip_masked_pbm (int X, int Y, int ScreenOffs, char far * Bitmap);
\r
62 The arguments are in the same order as those for x_put_masked_pbm in
\r
63 the module XPBITMAP. The bounding box is relative to the given
\r
64 ScreenOffs(et). This lets you perform page flipping without worrying about
\r
65 what screen you are clipping to -- it's always the current screen. The
\r
66 bitmap itself, of course, is not affected; clipping is performed on-the-
\r
67 fly. Both functions return an integer which indicates whether any part
\r
68 of the bitmap was inside the bounding box. If the entire bitmap was
\r
69 outside, a 1 is returned; otherwise, a 0.
\r
70 The third function in XPBITMAP, for which this module has no
\r
71 equivalent, copies from video RAM to system RAM. The absence of such a
\r
72 routine may seem at first like a disadvantage -- but this, like so many
\r
73 things in this life, is an illusion. You can use the unclipped routine,
\r
74 and clip the bitmap when you want to plot it back onto the screen.
\r
78 xclippbm.asm xclippbm.inc xlib.inc model.inc
\r
95 C Prototype: extern int x_clip_pbm (int X, int Y, int ScreenOffs, char
\r
98 Copies a planar bitmap from SRAM to VRAM, with clipping. If the entire
\r
99 bitmap turns out to be outside the bounding box, this function returns
\r
100 a 1; otherwise it returns a 0.
\r
104 C Prototype: extern int x_clip_masked_pbm (int X, int Y,
\r
105 int ScreenOffs, char far * Bitmap);
\r
107 Copies a planar bitmap from SRAM to VRAM, with clipping -- 0 bytes
\r
108 in the bitmap are not copied. If the entire bitmap turns out to be
\r
109 outside the bounding box, this function returns a 1; otherwise,
\r
113 --------------------------------------------------------------------------
\r
115 --------------------------------------------------------------------------
\r
116 The XMOUSE module implements very basic mouse handling functions. The way
\r
117 in which it operates is by installing an event handler function during
\r
118 initialization which subsequently intercepts and processes mouse events and
\r
119 automatically updates status variables such as mouse position and button
\r
120 pressed status. It does not support the full functionality of:
\r
126 This was done to primarily prevent unecessary impedences to performance,
\r
127 since the mouse handler function has the potential to degrade performance.
\r
128 It also saves me alot of coding which I was too lazy to do.
\r
130 Programs communicate with the mouse driver as with other devices, through
\r
131 an interrupt vector namely 33h. On generating an interrupt, the mouse driver
\r
132 expects a function number in AX and possibly other parameters in other
\r
133 registers and returns information via the registers. A brief description
\r
134 of the mouse functions follows:
\r
136 --------------------------------------
\r
138 MS Mouse Driver Functions
\r
140 Mouse Initialization 0
\r
143 Get Mouse Position & Button Status 3
\r
144 Set Mouse Cursor Position 4
\r
145 Get Button Press Information 5
\r
146 Get Button Release Information 6
\r
147 Set Min/Max Horizontal Position 7
\r
148 Set Min/Max Vertical Position 8
\r
149 Define Graphics Cursor Block 9
\r
150 Define Text Cursor 10
\r
151 Read Mouse Motion Counters 11
\r
152 Define Event Handler 12
\r
153 Light Pen Emulation Mode ON 13
\r
154 Light Pen Emulation Mode OFF 14
\r
155 Set Mouse Mickey/Pixel Ratio 15
\r
156 Conditional Hide Cursor 16
\r
157 Set Double-Speed Threshold 19
\r
158 --------------------------------------
\r
160 In practice only afew of these functions are used and even fewer when the
\r
161 mouse status is monitored by an event handler function such as is used in
\r
164 The most important thing to note when using the mouse module is that the
\r
165 mouse event handler must be removed before exiting the program. It is a good
\r
166 idea to have an exit function (see the C "atexit" function) and include the
\r
167 line "x_mouse_remove();" along with any other pre-exit cleanup code.
\r
169 See also: XDETECT for mouse detection.
\r
173 xmouse.asm xlib.inc model.inc
\r
181 MouseInstalled - WORD - Indicates whether mouse handler installed
\r
182 MouseHidden - WORD - Indicates whether mouse cursor is hidden
\r
183 MouseButtonStatus - WORD - Holds the mouse button status
\r
184 MouseX - WORD - Current X position of mouse cursor
\r
185 MouseY - WORD - Current Y position of mouse cursor
\r
186 MouseFrozen - WORD - Disallows position updates if TRUE
\r
187 MouseColor - BYTE - The mouse cursors colour
\r
194 C Prototype: int x_mouse_init()
\r
196 Initialize the mouse driver functions and install the mouse event handler
\r
197 function. This is the first function you must call before using any of the
\r
198 mouse functions. This mouse code uses the fastest possible techniques to
\r
199 save and restore mouse backgrounds and to draw the mouse cursor.
\r
201 WARNING: This function uses and updates "NonVisual_Offset" to allocate
\r
202 video ram for the saved mouse background.
\r
204 LIMITATIONS: No clipping is supported horizontally for the mouse cursor
\r
205 No validity checking is performed for NonVisual_Offs
\r
207 **WARNING** You must Hide or at least Freeze the mouse cursor while drawing
\r
208 using any of the other XLIB modules since the mouse handler may
\r
209 modify vga register settings at any time. VGA register settings
\r
210 are not preserved which will result in unpredictable drawing
\r
211 behavior. If you know the drawing will occur away from the
\r
212 mouse cursor set MouseFrozen to TRUE (1), do your drawing
\r
213 then set it to FALSE (0). Alternatively call "x_hide_mouse",
\r
214 perform your drawing and then call "x_show_mouse". Another
\r
215 alternative is to disable interrupts while drawing but usually
\r
216 drawing takes up alot of time and having interrupts disabled
\r
217 for too long is not a good idea.
\r
219 x_define_mouse_cursor
\r
220 ---------------------
\r
223 void x_define_mouse_cursor(char far *MouseDef, unsigned char MouseColor)
\r
225 MouseDef - a pointer to 14 characters containing a bitmask for all the
\r
227 MouseColor - The colour to use when drawing the mouse cursor.
\r
229 Define a mouse cursor shape for use in subsequent cursor redraws. XMouse
\r
230 has a hardwired mouse cursor size of 8 pixels across by 14 pixels down.
\r
232 WARNING: This function assumes MouseDef points to 14 bytes.
\r
234 Note: Bit order is in reverse. ie bit 7 represents pixel 0 ..
\r
235 bit 0 represents pixel 7 in each "MouseDef" byte.
\r
240 C Prototype: void x_show_mouse()
\r
242 Makes the cursor visible if it was previously hidden.
\r
243 See Also: "x_hide_mouse".
\r
248 C Prototype: void x_hide_mouse()
\r
250 Makes the cursor hidden if it was previously visible.
\r
251 See Also: "x_show_mouse".
\r
256 C Prototype: void x_remove_mouse()
\r
258 Stop mouse event handling and remove the mouse handler.
\r
260 NOTE: This function MUST be called before quitting the program if
\r
261 a mouse handler has been installed
\r
266 C Prototype void x_position_mouse(int x, int y)
\r
268 Positions the mouse cursor at the specified location
\r
273 C Prototype: void x_update_mouse()
\r
275 Forces the mouse position to be updated and cursor to be redrawn.
\r
276 Note: this function is useful when you have set "MouseFrozen" to true.
\r
277 Allows the cursor position to be updated manually rather than
\r
278 automatically by the installed handler.
\r
280 --------------------------------------------------------------------------
\r
282 --------------------------------------------------------------------------
\r
284 Wheel Have to See About That
\r
285 by Matthew MacKenzie
\r
287 The XCIRCLE module contains two functions, neither of which should be
\r
289 o x_circle, oddly enough, draws a circle.
\r
290 o x_filled_circle does too, only the circle is filled (in some
\r
291 libraries this is called a disc).
\r
293 The word `circle' here refers to a round thing which is as many
\r
294 pixels tall as across. It only looks like a circle in 320x240 mode --
\r
295 the original mode X -- and in 376x282 mode.
\r
296 In both functions, the circle is specified by the coordinates of the
\r
297 upper-left-hand corner of the smallest box which holds it, and the
\r
298 diameter. Some circle functions have you specify a center point;
\r
299 this system is kind of odd because a circle with an even diameter does
\r
300 not have a particular pixel for a center. Every circle, on the other
\r
301 hand, has a box with an upper-left corner.
\r
302 No bounds are checked. A diameter of zero will draw nothing, and
\r
303 a negative diameter will blow your VGA board into hundreds of thousands
\r
304 of tiny little smoldering fragments. Neither function supports clipping.
\r
305 The calculation of the circle is based on an algorithm described
\r
306 by Michael P. Lindner in a letter to the editor on page 8 of Dr. Dobb's
\r
307 Journal #169 (October 1990). The algorithm has been rearranged to
\r
308 allow drawing and moving the plots in the eight octants to be performed
\r
309 in one step, so that each pixel does not have to be loaded into the CPU
\r
310 twice. x_filled_circle does not take advantage of this optimization
\r
311 because it handles different parts of each plot at different times.
\r
315 xcircle.asm xcircle.inc xlib.inc model.inc
\r
325 C Prototype: extern void x_circle (WORD Left, WORD Top, WORD Diameter,
\r
326 WORD Color, WORD ScreenOffs);
\r
328 Draws a circle with the given upper-left-hand corner and diameter,
\r
329 which are given in pixels.
\r
334 C Prototype: extern void x_filled_circle (WORD Left, WORD Top,
\r
335 WORD Diameter, WORD Color, WORD ScreenOffs);
\r
337 Draws a filled circle with the given upper-left-hand corner and
\r
341 --------------------------------------------------------------------------
\r
343 --------------------------------------------------------------------------
\r
345 This module implements a set of functions to detect the PC's hardware
\r
350 xdetect.asm xdetect.inc model.inc
\r
382 MouseButtonCount - WORD - The number of buttons on the detected mouse
\r
383 MouseVersion - WORD - Mouse driver version (High byte = Major version
\r
384 Low byte = minor version)
\r
385 MouseType - BYTE - The mouse type
\r
386 MouseIRQ - BYTE - The IRQ number used by the mouse driver
\r
393 C Prototype: extern int x_graphics_card();
\r
395 This function returns the type of graphics card installed. See defines
\r
400 C Prototype: extern int x_processor();
\r
402 This function returns the type of processor installed. A 486 registers
\r
403 as a 386. See defines above.
\r
407 C Prototype: extern int x_coprocessor();
\r
409 This function returns 1 of a numeric co-processor is present, 0 if not.
\r
410 The type is not detected but it's mnot really necessary as the processor
\r
411 type usually determines the numeric coprocessor type
\r
415 C Prototype: extern int x_mousedriver();
\r
417 This function returns 1 of a mouse driver is installed, 0 otherwise.
\r
418 If a mouse driver is detected the mouse related variable (above) are
\r
421 --------------------------------------------------------------------------
\r
423 --------------------------------------------------------------------------
\r
425 Handle based file I/O functions.
\r
427 See any good DOS programming reference for more information on int 21h
\r
432 xfileio.asm xfileio.inc model.inc
\r
460 C Prototype: extern int f_open(char * filename, char access);
\r
462 Opens a file according to the access char:
\r
464 F_RDONLY = read only - If doesnt exist return error
\r
465 F_WRONLY = write only - If doesnt exist create it otherwise clear it
\r
466 F_RDWR = read/write - If doesnt exist create it
\r
468 Returns the file handle on success, FILE_ERR on failure
\r
474 C Prototype: extern int f_close(int handle);
\r
476 Closes the file associated with the specified handle
\r
478 Returns 0 on success, FILE_ERR on failure
\r
486 extern int f_read(int handle,char near * buffer, int count);
\r
488 Reads a block of count bytes from the file specified by the handle
\r
489 into the near buffer
\r
491 Returns count on success, FILE_ERR on failure
\r
498 extern int f_readfar(int handle,char far * buffer, int count);
\r
500 Reads a block of count bytes from the file specified by the handle
\r
501 into the far buffer
\r
503 Returns count on success, FILE_ERR on failure
\r
509 C Prototype: extern int f_write(int handle, char near * buffer, int count);
\r
511 Writes a block of count bytes to the file specified by the handle
\r
512 from the near buffer
\r
514 Returns count on success, FILE_ERR on failure
\r
519 C Prototype: extern int f_write(int handle, char far * buffer, int count);
\r
521 Writes a block of count bytes to the file specified by the handle
\r
522 from the far buffer
\r
524 Returns count on success, FILE_ERR on failure
\r
530 C Prototype: extern long int f_seek(int handle, long int position,
\r
533 Moves the file pointer according to the position and method code
\r
535 Returns file pointer position on success, FILE_ERR on failure
\r
543 extern long int f_filelength(int handle)
\r
545 Returns the length of the file associated with the specified handle
\r
547 Returns file length on success, FILE_ERR on failure
\r
555 extern long int f_tell(int handle)
\r
558 Returns file pointer position on success, FILE_ERR on failure
\r
560 --------------------------------------------------------------------------
\r
562 --------------------------------------------------------------------------
\r
564 This module implements a number of functions comprising an RLE encoding
\r
567 RLE stands for RUN LENGTH ENCODING. It is a quick simple data compression
\r
568 scheme which is commonly used for image data compression or compression
\r
569 of any data. Although not the most efficient system, it is fast, which is
\r
570 why it is used in image storage systems like PCX. This implementation is
\r
571 more efficient than the one used in PCX files because it uses 1 bit to
\r
572 identify a Run Length byte as opposed to two in PCX files, but more on this
\r
575 This set of functions can be used to implement your own compressed image
\r
576 file format or for example compress game mapse for various levels etc.
\r
577 The uses are limited by your imagination.
\r
579 I opted for trading off PCX RLE compatibility for the improved compression
\r
582 Here is how the data is un-compressed to give an idea of its structure.
\r
585 STEP 1 read a byte from the RLE compressed source buffer.
\r
587 STEP 2 if has its high bit is set then the lower 7 bits represent the number
\r
588 of times the next byte is to be repeated in the destination buffer.
\r
589 if the count (lower 7 bits) is zero then
\r
590 we have finished decoding goto STEP 5
\r
593 STEP 3 Read a data from the source buffer and copy it directly to the
\r
594 destination buffer.
\r
597 STEP 4 Read a data byte from the source buffer and copy it to the destination
\r
598 buffer the number of times specified by step 2.
\r
601 STEP 5 Stop, decoding done.
\r
603 If the byte does not have the high bit set then the byte itself is transfered
\r
604 to the destination buffer.
\r
606 Data bytes that have the high bit already set and are unique in the input
\r
607 stream are represented as a Run Length of 1 (ie 81 which includes high bit)
\r
608 followed by the data byte.
\r
610 If your original uncompressed data contains few consecutive bytes and most
\r
611 have high bit set (ie have values > 127) then your so called
\r
612 compressed data would require up to 2x the space of the uncompressed data,
\r
613 so be aware that the compression ratio is extremely variable depending on the
\r
614 type of data being compressed.
\r
616 Apologies for this poor attempt at a description, but you can look up
\r
617 RLE in any good text. Alternatively, any text that describes the PCX file
\r
618 structure in any depth should have a section on RLE compression.
\r
624 xrletool.asm xrletool.inc model.inc
\r
638 Expands an RLE compresses source buffer to a destination buffer.
\r
639 returns the size of the resultant uncompressed data.
\r
643 extern unsigned int x_buff_RLDecode(char far * source_buff,
\r
644 char far * dest_buff);
\r
646 source_buff - The buffer to compress
\r
647 dest_buff - The destination buffer
\r
649 WARNING: buffers must be pre allocated.
\r
655 RLE Compresses a source buffer to a destination buffer and returns
\r
656 the size of the resultant compressed data.
\r
660 extern unsigned int x_buff_RLEncode(char far * source_buff,
\r
661 char far * dest_buff,unsigned int count);
\r
663 source_buff - The buffer to compress
\r
664 dest_buff - The destination buffer
\r
665 count - The size of the source data in bytes
\r
667 WARNING: buffers must be pre allocated.
\r
672 Returns the size the input data would compress to.
\r
676 extern unsigned int x_buff_RLE_size(char far * source_buff,
\r
677 unsigned int count);
\r
679 source_buff - The uncompressed data buffer
\r
680 count - The size of the source data in bytes
\r
686 RLE Compresses a source buffer to an output file returning
\r
687 the size of the resultant compressed data or 0 if it fails.
\r
691 extern unsigned int x_file_RLEncode(int handle,
\r
692 char far * source_buff,unsigned int count);
\r
694 source_buff - The buffer to compress
\r
695 handle - The file handler
\r
696 count - The size of the source data in bytes
\r
701 Expands an RLE compresses file to a destination RAM buffer.
\r
702 returns the size of the resultant uncompressed data.
\r
706 extern unsigned int x_buff_RLDecode(int handle,
\r
707 char far * dest_buff);
\r
709 handle - Input file handle
\r
710 dest_buff - The destination buffer
\r
715 --------------------------------------------------------------------------
\r
717 --------------------------------------------------------------------------
\r
719 This module implements eneral filled convex polygon and triangle
\r
742 void x_triangle(int x0, int y0, int x1, int y1, int x2, int y2,
\r
743 WORD color, WORD PageBase);
\r
745 This function draws a filled triangle which is clipped to the current
\r
746 clipping window defined by TopClip,BottomClip,LeftClip,RightClip.
\r
747 Remember: the X clipping variable are in BYTES not PIXELS so you
\r
748 can only clip to 4 pixel byte boundaries.
\r
756 void x_polygon(VERTEX *vertices, int num_vertices,
\r
757 WORD color, WORD PageBase);
\r
759 This function is similar to the triangle function but draws
\r
760 convex polygons. The vertices are supplied in the form of a FAR
\r
763 NOTE: a convex polygon is one such that if you draw a line from
\r
764 any two vertices, every point on that line will be within the
\r
767 This function works by splitting up a polygon into its component
\r
768 triangles and calling the triangle routine above to draw each one.
\r
769 Performance is respectable but a custom polygon routine might be
\r
773 --------------------------------------------------------------------------
\r
775 --------------------------------------------------------------------------
\r
777 This module implements a couple of general purpose flood fill functions
\r
792 int x_flood_fill(int x, int y, unsigned ofs, int color);
\r
794 This function performs the familiar flood filling used by many
\r
795 paint programs and of course the Borland BGI's flood fill function.
\r
796 The pixel at x,y and all adjacent pixels of the same color are filled
\r
797 to the new color. Filling stops when there are no more adjacent pixels
\r
798 of the original pixel's color. The function returns the number of
\r
799 pixels that have been filled.
\r
806 int x_boundary_fill(int x,int y,unsigned ofs,int boundary,int color);
\r
808 This function is a variant of the flood fill described above. This
\r
809 function, unlike the above function, can fill across color boundaries.
\r
810 Filling stops when the area being filled is fully enclosed by pixels
\r
811 of the color "boundary". Again, this function returns the number of
\r
814 -------------------------------------------------------------------------------
\r
816 -------------------------------------------------------------------------------
\r
820 Simulated Vertical Retrace Interrupt Module
\r
822 by Tore Jahn Bastiansen <toreba@ifi.uio.no>
\r
824 Inspired by REND386 v3.01 by Dave Stampe and Bernie Roehl
\r
826 The xvsync module uses timer 0 to simulate a vertical retrace interrupt.
\r
827 It's designed to significantly reduce the idle waiting time in Xlib.
\r
828 Why simulate the VRT interrupt ? Simply because a true VRT interrupt is
\r
829 not implemented on many VGA cards. Using a VRT interrupt as opposed to
\r
830 polling, can result in huge performance improvements for your code and
\r
831 help make animation much smoother than it would be using polling.
\r
833 Normally xlib waits for vsync when x_page_flip, x_set_start_address or
\r
834 x_put_pal_??? is called. This waiting period could be better utilized to do
\r
835 housekeeping calculations or whatever. The x_put_pal_??? functions also
\r
836 doesn't work very smoothly in conjunction with other functions that wait for
\r
837 the vertical retrace since each function introduces its own VRT delay.
\r
839 When using the vsync handler, the VRT delay is reduced to the absolute
\r
840 minumum which can result in a huge performance boost for your programs.
\r
842 When using double buffering, you may still have to wait before drawing,
\r
843 but you could do as much other work as possible, like this:
\r
847 <animate the palette>
\r
848 <do some collision detection and 3D calculations>
\r
849 <read the joystick>
\r
851 x_wait_start_address(); (Not needed with triple buffering)
\r
858 xvsync.asm xmain.asm xvsync.inc xmain.inc
\r
866 VsyncPeriod - WORD -time in 1.193 us between two vsyncs
\r
868 TicksPerSecond - WORD - number of vsyncs per second
\r
870 VsyncTimerInt - long - number of vsyncs since x_install_vsync_handler was
\r
871 called. Nice for game timing.
\r
875 x_install_vsync_handler
\r
876 -----------------------
\r
878 C Prototype: void x_install_vsync_handler(int VrtsToSkip);
\r
880 This function installs the vsync handler using timer 0. It's called
\r
881 about 100 microseconds before every vertical retrace.
\r
883 The VrtsToSkip value (>=1) defines the delay in VRT's between consecutive
\r
884 physical screen start address changes, thus allowing you to limit the
\r
885 maximum frame rate for page flips in animation systems. The frame rate
\r
886 is calculated as Vertical refresh rate / VrtsToSkip, eg for
\r
887 320x240 mode which refreshes at 60Hz a VrtsToSkip value of 3 will result
\r
888 in a maximum page flipping rate of 20Hz (frames per second)
\r
890 WARNING: Be sure to remove it before exiting.
\r
891 When used with a debugger, the system clock may speed up.
\r
893 x_remove_vsync_handler
\r
894 ----------------------
\r
896 C Prototype: void x_remove_vsync_handler
\r
898 This routine _MUST_ be called before exiting (or aborting) the program,
\r
899 or your system will crash.
\r
901 x_set_user_vsync_handler
\r
902 ------------------------
\r
904 C Prototype: void x_set_user_vsync_handler(void far (*f)());
\r
906 Installs a user routine to be called once each vertical retrace. The user
\r
907 handler have its own stack of 256 bytes , so be careful with the stack
\r
908 checking option in BC.
\r
909 WARNING: This installs an interrupt driven handler, beware of the following:
\r
910 Only 8086 registers are preserved. If you're using 386 code, save
\r
912 Don't do any drawing.
\r
913 Don't call any DOS functions.
\r
916 Well, you can update global variables if you're careful. And it's nice for
\r
917 palette animation. You can even do fades while loading from disk. You
\r
918 should use this instead of installing your own int08h routine and chain
\r
924 C Prototype: void x_wait_start_addr(void)
\r
926 You must call this function before drawing after a call to x_set_start_addr
\r
927 or x_page_flip when you are using the vsync handler and not using
\r
930 MODULE XMAIN additions
\r
934 Page2_Offs - WORD - Offset in video ram of third virtual screen. Set by
\r
937 WaitingPageOffs - WORD - Offset of page waiting to be invisible. Initially
\r
938 set by x_set_triple_buffer but is updated by x_page_flip. This
\r
939 variable is only used while triple buffering is on.
\r
941 VsyncHandlerActive - WORD - Indicates whether the vsync handler is installed.
\r
943 TripleBufferActive - WORD - Indicates whether triple-buffering is on.
\r
944 Set by x_triple_buffer.
\r
946 StartAddressFlag - WORD - This flag is set if there is a new start
\r
947 address waiting to be set by the vsync handler.
\r
949 WaitingStartLow - WORD - Needed by vsync handler. Keep off.
\r
950 WaitingStartHigh - WORD - Needed by vsync handler. Keep off.
\r
951 WaitingPelPan - WORD - Needed by vsync handler. Keep off.
\r
953 VsyncPaletteStart - WORD - Start index of video DAC register to be
\r
954 updated next vsync. Set by palette functions.
\r
956 VsyncPaletteCount - WORD - Number of palette entries to be outed next
\r
957 vsync. Set by palette functions.
\r
959 VsyncPaletteBuffer - BYTE[768] - Buffer containing values for the next
\r
967 C Prototype: void x_triple_buffer(WORD PageHeight);
\r
969 This function behaves like x_double_buffer, but when used with
\r
970 x_install_vsync_handler you can draw immediately after a page flip.
\r
971 When x_page_flip is called, VisiblePageOffs is set to the page that
\r
972 will be display next vsync. Until then, WaitingPageOffs will be displayed.
\r
973 You can draw to HiddenPageOffs .
\r
978 --------------------------------------------------------------------
\r
980 --------------------------------------------------------------------
\r
986 In my opinion Doctor Dobbs Journal is the best reference text for
\r
987 VGA Mode X graphics:
\r
989 Issue 178 Jul 1991 : First reference to Mode X
\r
990 Article Abstract : VGA's undocumented Mode X supports page flipping,
\r
991 makes off screen memory available, has square pixels,
\r
992 and increases performance by as muck as 4 times.
\r
994 Issue 179 Aug 1991 : Continuation
\r
995 Article Abstract : Michael discusses latches and VGA's undoccumented
\r
998 Issue 181 Sep 1991 : Continuation
\r
999 Article Abstract : Michael puts the moves on animation using VGA's 256
\r
1002 Issue 184 Oct 1991 : First of a continuing series covering 3-D animation
\r
1003 using VGA's Mode X. This series is still ongoing
\r
1005 Article Abstract : Michael moves into 3-D animation, starting with basic
\r
1006 polygon fills and page flips.
\r
1012 Mode X is a derrivative of the VGA's standard mode 13h (320x200 256 color).
\r
1013 It is a (family) of undocumented video modes that are created by tweaking
\r
1014 the VGA's registers. The beauty of mode X is that it offers several
\r
1015 benefits to the programmer:
\r
1016 - Multiple graphice pages where mode 13h doesn't allowing for page flipping
\r
1017 (also known as double buffering) and storage of images and data in
\r
1018 offscreen video memory
\r
1019 - A planar video ram organization which although more difficult to program,
\r
1020 allows the VGA's plane-oriented hardware to be used to process pixels in
\r
1021 parallel, improving performance by up to 4 times over mode 13h
\r
1023 See issue 178-179 of D.D.J. for a full description of VGA's Mode X.
\r
1025 WHAT IS A SPLIT SCREEN ?
\r
1026 ------------------------
\r
1028 A split screen is a neat hardware feature offered by the EGA and VGA video
\r
1029 cards. A split screen is a mode of graphics operationin which the Hardware
\r
1030 splits the visual graphics screen horizontally and treats both halves as
\r
1031 individual screens each starting at different locations in video RAM.
\r
1033 The bottom half (which is usually referred to as the split screen) always
\r
1034 starts at address A000:0000 but the top half's starting address is user
\r
1037 The most common application of split screens in games is the status display
\r
1038 in scrolling games. Split screens make this sort of game simpler to program
\r
1039 because when the top half window is scrolled the programmer does not have to
\r
1040 worry about redrawing the bottom half.
\r
1042 WHAT IS DOUBLE BUFFERING ?
\r
1043 --------------------------
\r
1045 Double buffering (also known as page flipping) is the technique most often
\r
1046 used to do animation. it requires hardware that is capable of displaying
\r
1047 multiple graphics pages (or at least 2). Animation is achieved by drawing
\r
1048 an image in the non visible screen and then displaying the non visible
\r
1049 screen. Once the page has been flipped the process starts again. The next
\r
1050 frame of the animation is drawn on the non visible screen, the page is
\r
1051 flipped again etc.
\r
1054 WHAT IS TRIPPLE BUFFERING ?
\r
1055 --------------------------
\r
1057 Triple buffering is similar to double buffering in many ways, but it
\r
1058 relies on 3 pages being defined for animation. The main selling point
\r
1059 of triple buffering is that it eliminates the need to wait for the
\r
1060 vertical retrace to flip pages before drawing on the new page thus
\r
1061 alowing the programmer to start building the next animation frame
\r
1062 immediately after completing the current one. Heres how it works:
\r
1064 With double buffering, once you complete drawing the hidden page and
\r
1065 youre ready to flip pages, you have to wait for the VGA hardware to
\r
1066 actually flip the page (during the vertical retrace) before you start
\r
1067 drawing the next page otherwise you will be drawing on the visible page.
\r
1069 With triple buffering you cycle between three pages, thus the page you
\r
1070 draw on is guaranteed not to be visible. I know this is a poor
\r
1071 description but it really is quite simple
\r
1073 Triple buffering can acheive the fastest possible animation under the
\r
1074 right conditions but the draw back is that more video RAM is required. If
\r
1075 you wish to store bitmaps in video ram such as background tiles, double
\r
1076 buffering would be the better alternative.
\r
1082 Mode X is a derrivative of the VGA's standard mode 13h (320x200 256 color).
\r
1083 It is a (family) of undocumented video modes that are created by tweaking
\r
1084 the VGA's registers. The beauty of mode X is that it offers several
\r
1085 benefits to the programmer:
\r
1086 - Multiple graphice pages where mode 13h doesn't allowing for page flipping
\r
1087 (also known as double buffering) and storage of images and data in
\r
1088 offscreen video memory
\r
1089 - A planar video ram organization which although more difficult to program,
\r
1090 allows the VGA's plane-oriented hardware to be used to process pixels in
\r
1091 parallel, improving performance by up to 4 times over mode 13h
\r
1093 Again see D.D.J. for an in depth discussion of animation using Mode X.
\r
1095 -----------------------------------------------------------------------
\r