home *** CD-ROM | disk | FTP | other *** search
/ Boston 2 / boston-2.iso / DOS / PROGRAM / PASCAL / VGAFONT / VGA_FONT.DOC < prev    next >
Text File  |  1993-12-01  |  24KB  |  529 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.                                                           2/13/90
  7.  
  8.         Joseph J. Tamburino
  9.         7 Christopher Rd.
  10.         Westford, MA 01886
  11.         Prodigy:  NWNJ91A
  12.         CompuServe:  70033,107
  13.         Phone:  508-692-7756
  14.  
  15.  
  16.         Dear Fellow Programmer:
  17.  
  18.              I have written some routines that I would love to share with
  19.         you.  These routines allow graphics to be displayed with ordinary
  20.         EGA or VGA text modes.  The routines work by modifying unused
  21.         characters to represent graphic primitives as the primitives are
  22.         being drawn.  For instance, if the Line procedure was called, a
  23.         line of graphic characters would be allocated and modified so that
  24.         a line appears on the screen, just as it would with a standard
  25.         graphics mode.
  26.  
  27.              These routines are still under development, so no claim is
  28.         made to ensure that they work 100%.  The demonstration program has
  29.         been tested on a 256K VGA system, however the code has been
  30.         designed with the intention that EGA users might also use them.
  31.  
  32.         Files Included
  33.         --------------
  34.  
  35.         These files should be included with the archived version:
  36.  
  37.         VGAfont.PAS:   The demonstration program, written with Turbo Pascal
  38.                        version 5.0
  39.         VGAfont.EXE:   The compiled demonstration program.
  40.         V_FONT_U.PAS:  The interface to the actual assembler routines, in
  41.                        unit format.
  42.         V_FONT_U.TPU:  The compiled V_FONT_U unit.
  43.         VGA_FONT.ASM:  The actual font redefinition routines.
  44.         VGA_FONT.OBJ:  The compiled version of VGA_FONT.ASM
  45.         VGA_FONT.DOC:  This file.
  46.  
  47.  
  48.              Note that all of the filenames use underscores except for the
  49.         VGAfont files.  The reason for this inconsistency is that Symdeb &
  50.         MapSym, the debuggers I used to debug this, do not support main
  51.         filenames containing underscores, for some very strange reason.
  52.  
  53.  
  54.         How to use the routines
  55.         -----------------------
  56.  
  57.              Since the individual routines are clearly documented, I will
  58.         not bother to discuss all of them here.  Instead, I'll just discuss
  59.         the overall use of the V_FONT_U unit.
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.              The V_FONT_U unit stands for VGA_FONT_UNIT.  None of the
  73.         filenames even hint at the possibility that the routines will
  74.         support EGA also, however they should work for EGA adapters.  Since
  75.         I have not tried them on an EGA system, I cannot be sure that they
  76.         will actually work on them, however they should work on all VGAs.
  77.  
  78.              The first thing that the body of your Pascal program should do
  79.         is to set the number of scan lines the program will use.  The
  80.         reason for this is that on the VGA adapter, the default 400-line
  81.         screen mode displays the standard 8-bit wide characters using 9-bit
  82.         wide display fields.  Since the fields are too big, an extra
  83.         vertical line is displayed to the right of all characters, except
  84.         for the designated border characters which are displayed with their
  85.         right most pixel extended to the 9th position.  This setup tends to
  86.         make images appear perforated, or like venetian blinds, and thus
  87.         may not be appropriate for your needs.  The 350-line & 200-line
  88.         modes solve this problem by only displaying characters at 8-bits
  89.         per character.  To change to one of these modes, use the
  90.         Make8BitChars procedure with the number of scan-lines you want as
  91.         the parameter.  To revert back to 9-bit display fields, call the
  92.         Make9BitChars procedure.  These settings remain in effect until
  93.         they are changed back, even if the display mode is changed.
  94.  
  95.              The program also must set the EGA_VGA flag to either EGA or
  96.         VGA depending on the adapter being used.
  97.  
  98.              The next step is to call the FontInit procedure with two
  99.         buffers to be used with the font procedures.  The first parameter
  100.         is a pointer to a 6144-byte font-table buffer, and the second is a
  101.         4096-byte screen buffer to record the screen's contents.  See the
  102.         demonstration program for details.
  103.  
  104.              Once done, use the graphics primitives in the same fashion you
  105.         are probably used to doing.  For instance, to draw a line from the
  106.         top-left corner to the bottom-right in blue, use the statement:
  107.         Line(0,0,MaxX,MaxY,1).  To draw a horizontal line at the bottom of
  108.         the screen using green, use Hlin(0,MaxY,MaxX,2).
  109.  
  110.              Each time a graphics primitive is executed, the variable
  111.         TotalUsed is updated with the total number of graphics characters
  112.         allocated as of the time it is being sampled.  It is important to
  113.         keep track of this variable, because if it reaches 384 (the maximum
  114.         # of characters that can be allocated), no more new characters can
  115.         be allocated.  Keep in mind that if you draw an image directly onto
  116.         an existing image (with no overlap), no new characters will be
  117.         allocated, since they have already been allocated.  Also keep in
  118.         mind that if you erase an area using color 0, any characters that
  119.         end up becoming zero will be de-allocated, and substituted with the
  120.         space character.  This happens with any graphics primitive you use.
  121.  
  122.              To clear and deallocate all of the characters being used for
  123.         graphics, use the ClearChars procedure.  As an argument, include
  124.         the same buffer-area you have used previously with FontInit or
  125.  
  126.  
  127.                                      2
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138.         GetScrn to restore the text-screen to the desired format.  Again,
  139.         see the demonstration program for clear examples.
  140.  
  141.              If you intend to do animation, the Freeze & UnFreeze
  142.         procedures will undoubtedly be of help.  Freeze copies the current
  143.         page 0 image to another page, and displays that page.  Meanwhile,
  144.         all graphics functions still effect page 0 (but not the display).
  145.         UnFreeze flips back to page 0 to display the changes made during
  146.         the time the image was "frozen".  These procedures are necessary
  147.         since the act of constantly updating & changing the character set
  148.         and screen produces a substantial amount of flicker.
  149.         Unfortunately, the WriteFont procedure (used by ClearChars, and all
  150.         other graphics primitives) always resets the current video page to
  151.         0, resulting in a premature unfreeze of the display.  So the freeze
  152.         procedure really must be used twice:  once before, and once after a
  153.         graphics primitive is executed.  Even then, the flickering is not
  154.         completely disabled.  The UnFreeze procedure can be used at any
  155.         time;  in fact, it doesn't have to be used at all since the
  156.         graphics primitives automatically do the equivalent of UnFreeze.
  157.         Once again, see the demonstration program for examples.
  158.  
  159.              You may wonder why the WriteFont procedure changes the video
  160.         page, and what can be done about it since the change is so
  161.         inconvenient in an animation sequence.  The WriteFont procedure
  162.         simply uses function 11h of INT 10h to copy the font information to
  163.         the adapter's font memory.  Why INT 10h changes the video mode is
  164.         beyond me.  However it is, of course, possible to bypass the BIOS
  165.         and copy the font table directly to the adapter's memory yourself.
  166.         I tried this, and two problems occurred.  First of all, I couldn't
  167.         get all of the characters to copy for some reason.  I'm sure this
  168.         was my own error, but I couldn't see anything wrong with my coding.
  169.         Secondly, the font-writing seems to produce terrible hardware-
  170.         generated snow on the screen.  Waiting for vertical retrace
  171.         decreases the amount of flicker, but by no means does it eliminates
  172.         it.  Since I could never get these problems resolved, I had to
  173.         continue using the BIOS.  If anyone knows how to bypass the BIOS in
  174.         order to not tamper with the video-page setting, and yet remain
  175.         flicker-free, let me know -- please!
  176.  
  177.              The Ellipse procedure, by the way, supports solid fills, as
  178.         well as outline fills.  To achieve solid fills, set bit 7 of the
  179.         color byte to high.  (This bit is stripped before the ellipse is
  180.         displayed).
  181.  
  182.  
  183.         Speed
  184.         -----
  185.  
  186.              As you will note, my routines are not very fast.  This is
  187.         because every single routine calls the main Pset routine to plot
  188.         each individual point separately.  Although modular, this method is
  189.         very slow.  A better way to program graphics routines is to have
  190.         the routines keep track of the bit position and character number
  191.         itself, and decrement and increment when as needed.  While this is
  192.  
  193.                                      3
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202.  
  203.  
  204.         relatively easy for regular graphics modes, there would be a great
  205.         deal of work involved when doing this for text-mode.  However, you
  206.         are encouraged to try and speed the routines up yourself.  My
  207.         suggestion to you is to speed the Hlin2 procedure up first, since
  208.         this procedure is used by Box, OpenBox, and Ellipse.  Line & Vlin
  209.         should probably be improved next.  Another suggestion would be to
  210.         design useful Get & Put procedures.  Please let me know of any
  211.         improvements you make, so I can include both the code and your name
  212.         in future revisions of the code.
  213.  
  214.  
  215.         Attributes and 512-character fonts
  216.         ----------------------------------
  217.  
  218.              In order to have 256 character fonts (the standard), it is
  219.         required to have eight bits of information.  These eight bits forms
  220.         what is known as the IBM ASCII code (the smallest number of bits a
  221.         computer can use and still remain ASCII compatible is six.  This
  222.         provides 64 possible symbols and does not allow lowercase).  If I
  223.         were to program these routines using only the standard 256-
  224.         character font, I would have to decide which of those characters I
  225.         am able to "give up" for graphics purposes.  If it were me, I would
  226.         use the upper 128 characters, those used by IBM to produce borders
  227.         and things.  As it turns out, 128 characters is not sufficient for
  228.         most applications, because it doesn't allow very much graphic
  229.         information to be displayed at once (although the actual amount of
  230.         information possible varies considerably with the way the images
  231.         are displayed).
  232.  
  233.              By using 512-character fonts, it is possible to have the
  234.         original 128 plus 256 new characters for a total of 384 characters.
  235.         This number is still too small, but is the most characters a VGA
  236.         card can produce at once.  The problem, however, is how to refer to
  237.         the new nine-bit character code.  The 80x25 color IBM screen (mode
  238.         3) only provides eight bits for the character code, and eight for
  239.         the attribute code.  Obviously, to use 512-character sets, it is
  240.         necessary to "steal" one of the attribute bits.  The designers of
  241.         the VGA decided to use the high-order bit of the forground
  242.         attribute field (bit 3, or the intensity bit).  Personally, if I
  243.         had the choice, I would have used bit 7, the high bit of the
  244.         background field.  This is because, traditionally, that bit was
  245.         sometimes reserved for blinking, so people became used to only
  246.         having 8 background color choices.
  247.  
  248.              But they choose to alter the forground.  This leads to the
  249.         next question:  So what color will 7 represent?  How about 15?  The
  250.         question is:  How is the 4'th bit represented on the screen?  The
  251.         answer is:  Normally the bit is represented in the usual fashion.
  252.         This means that if you had an image comprised of some low-order
  253.         characters, and some high-order characters, and all characters were
  254.         displayed with attribute 7, then some of the image would appear
  255.         dark-white, and some of it would appear light-white.  The same goes
  256.         for all the other colors.
  257.  
  258.  
  259.                                      4
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270.              To get around this, it is possible to program the EVGA card to
  271.         mask this bit in such a way to only display the low-intensity
  272.         colors.  And this is what the MaskColors procedure does.  By the
  273.         way, the Make512chars procedure sets up 512-character mode.  Once
  274.         again, find the occurrence of MaskColors in the demo program and
  275.         observe how it uses the procedure (it's in the EllipseDemo
  276.         procedure).  The Make512chars procedure is used during the
  277.         initialization of the unit, and is not something you have to worry
  278.         about -- the unit will always use 512-character fonts.  Please note
  279.         that although you can only have 8 colors in this setup, you are not
  280.         required to use the standard 8 colors.  For instance, the VGA
  281.         allows you to use any 8 of the available 256K colors it has
  282.         available, and the EGA will allow any 8 of 64 colors.
  283.  
  284.  
  285.         Global Constants and Variables
  286.         ------------------------------
  287.  
  288.              The V_FONT_U unit provides the following global constants and
  289.         variables for use in your main program:
  290.  
  291.         EGA,VGA:       For use with the EGA_VGA boolean flag to represent
  292.                        the type of adapter being used.  I.e., EGA_VGA:=EGA
  293.                        will setup for an EGA adapter.  Note:  for SuperEGA,
  294.                        the VGA mode may work better.
  295.  
  296.         LargestChar:   The largest character code (511).
  297.  
  298.         SmallestChar:  The smallest character code (128).
  299.  
  300.         FontSize:      The size for 384 characters at 16 bytes (points)
  301.                        each (1800h bytes).
  302.  
  303.         MaxX,MaxY:     The maximum coordinate possible (variables that
  304.                        depend on the # of lines.  MaxX is always 639).
  305.  
  306.         EGA_VGA:       Boolean variable that defaults to VGA (see above).
  307.  
  308.         TotalUsed:     Variable that contains the number of characters that
  309.                        are currently allocated and used by V_FONT_U.  This
  310.                        variable will decrease only if a black (attribute 0)
  311.                        image is drawn that completely covers one or more
  312.                        character cells or if the ClearChars procedure is
  313.                        called.
  314.  
  315.  
  316.         Using and Improving the Code
  317.         ----------------------------
  318.  
  319.              Using the code, as you can see by observing the demo, is
  320.         fairly straightforward.  To use graphics in text mode, the
  321.         following actions must be performed by the application:
  322.  
  323.  
  324.  
  325.                                      5
  326.  
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336.         1)  Set the number of displayable pixels per character cell with
  337.             the Make8BitChars or the Make9BitChars procedures.  Note that 9
  338.             bit characters are made up of only 8 pixels, although the VGA
  339.             card will display 9.  The Make8BitChars procedure contains a
  340.             parameter which defines the number of lines to display (350 or
  341.             200).  The Make9BitChars procedure automatically uses 400
  342.             lines.
  343.  
  344.         2)  Select 80x25 color or monochrome text mode (mode 2 or 3).
  345.  
  346.         3)  Initialize the V_FONT_U init by calling FontInit with two
  347.             parameters:  The address of a font buffer from 1 to FontSize,
  348.             and the address of the screen buffer from 1 to 4096.  Note that
  349.             ClearChars will reset the screen to look as it does when this
  350.             procedure is called.  To change the way the screen looks to
  351.             ClearChars later on, use the GetScrn procedure.
  352.  
  353.         4)  Use standard text routines such as Write, WriteLn, GotoXY,
  354.             etc.,  as you normally do, and also take advantage of the new
  355.             graphics primitives.
  356.  
  357.         5)  Keep track of TotalUsed to make sure that it doesn't equal 384.
  358.             If it does, no more graphics routines will take effect if they
  359.             need to define new cells.
  360.  
  361.  
  362.              That's all there really is to this in general.  To improve the
  363.         code, many things can be done.  For starters, there is no way of
  364.         preventing duplicate characters from being generated.  For
  365.         instance, a call to Hlin might produce a series of similar solid
  366.         line characters.  This is a complete waste of space.  However, to
  367.         change this would require a huge slow down of processor time if the
  368.         change is to occur dynamically.  To see this, imagine what would
  369.         happen if we did produce a horizontal line using only one
  370.         character.  What would happen if we then decided to draw a vertical
  371.         line through the middle, intersecting the previous line?  The
  372.         intersection would produce a "+" character.  And this character
  373.         would suddenly appear duplicated throughout every instance of the
  374.         original solid line character.  In effect, the line would suddenly
  375.         look something like:            |
  376.                               +++++++++++++++++++++
  377.                                         |
  378.  
  379.              Although the line would really not be perforated.  To get
  380.         around this problem, a table would be required to see if a
  381.         character is duplicated in another place BEFORE changing it.  If it
  382.         is, a new character would be allocated, and put into position.  The
  383.         actual point-plotting procedure would have to be expanded in a
  384.         different way, also.  In stead of blindly putting down character
  385.         cells, it would have to check and see if there was anything else
  386.         there.  Still, this is a feasible change.
  387.  
  388.              Another method would be to define one single procedure called
  389.         "Consolidate" or something to that effect.  It's job would be to
  390.  
  391.                                      6
  392.  
  393.  
  394.  
  395.  
  396.  
  397.  
  398.  
  399.  
  400.  
  401.  
  402.         look at every character and see what can be duplicated.  Instead of
  403.         doing it dynamically, it would be more of a periodic type
  404.         situation.  If there are any plans to be able to plot points AFTER
  405.         the consolidate procedure has executed, a table would be required
  406.         to store all duplicated characters, and further Pset operations
  407.         would have to define new characters if one of those has been
  408.         encountered (just like the last example).
  409.  
  410.              Another possible change would be to abandon the top-down
  411.         design that all the graphics primitives use;  they all call the
  412.         single and lengthy Pset procedure.  As you'll see, this would take
  413.         quite a lot of work.  In the end, who knows whether it will be
  414.         worth it or not.  If you're not quite sure what I am referring to,
  415.         take this simple example:  The 320x200x256 color mode (13h) is a
  416.         simple array of contiguous bytes.  Therefore, here are two
  417.         assembly-language procedure capable of drawing a horizontal line
  418.         from x1 to x2 at the vertical line y1:
  419.  
  420.              mov       cx,x2
  421.              sub       cx,x1
  422.              inc       cx
  423.         Looph:push     x1       ; Provide parameter x1
  424.              push      y1       ; Provide parameter y1
  425.              call      Pset
  426.              inc       x1
  427.              loop      Looph
  428.  
  429.              (Note that the pixel color is ignored).  You'll find a very
  430.         similar construct in the Hlin procedure provided in VGA_FONT.ASM.
  431.         Here is another method for the 320x200x256 mode:
  432.  
  433.              mov       ax,320
  434.              mul       y1
  435.              add       ax,x1
  436.              mov       di,ax
  437.              mov       cx,x2
  438.              sub       cx,x1
  439.              inc       cx
  440.              rep stosb
  441.  
  442.              Of course, this is an incomplete example;  the segment
  443.         register has not been set, and the direction flag has not been
  444.         cleared.  But notice the difference between the two subroutines.
  445.         In the first routine, a large amount of instructions had to be
  446.         performed for each and every pixel in the line.  For the second,
  447.         the whole line was drawn using only one instruction (actually a
  448.         prefix and a complete instruction).  Obviously the second will run
  449.         faster.  Although it is non-modular, it is the better choice to use
  450.         in most applications.  If you examine the code for Pset in
  451.         VGA_FONT.ASM, you'll note that in the course of execution, several
  452.         other lengthy procedures also get called, which is why the routines
  453.         execute so slowly.  Nevertheless, it would be impossible to code an
  454.         Hlin routine for text mode the same way I did for mode 13h.
  455.         Chances are, however, that it could be made faster via successive
  456.  
  457.                                      7
  458.  
  459.  
  460.  
  461.  
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468.         shifting of the next cell pixel position, instead of calling Pset
  469.         for every single pixel.
  470.  
  471.              Actually, the longest part of the Pset routine is the call to
  472.         the BIOS to update the character fonts.  To circumvent this,
  473.         procedures that use Pset actually use Pset2 instead.  Pset2 has the
  474.         same function as Pset except that the character font is not
  475.         updated.  Obviously, this means that such a graphics primitive must
  476.         do this itself at the end.  Likewise, Hlin also has a counterpart
  477.         called Hlin2 which does not update the font, thereby enabling a
  478.         procedure such as box to save that operation for last.
  479.  
  480.  
  481.              Other changes:  Please see the V_FONT_U.PAS file for more
  482.         update suggestions, and feel free to make changes as you feel are
  483.         appropriate.  Please keep in touch with me so I know what kinds of
  484.         wonderful things are happening to my code.
  485.  
  486.  
  487.         Royalties
  488.         ---------
  489.  
  490.              Unless I feel that you have made a significant ["significant"
  491.         is subject to be defined in accordance to my own discretion]
  492.         improvement to this package, there is a $10.00 fee to use any or
  493.         all of this code in your own program, if you plan to release the
  494.         program to other individuals, companies, or fellow employees.  This
  495.         fee applies regardless of whether you sell the program for money,
  496.         or just give it away free.  Note that this code is copyright (c)
  497.         February 1990, by Joseph J. Tamburino.
  498.  
  499.              If you have made a significant improvement, you will be
  500.         entitled to increase the fee as long as $10.00 still goes to Joseph
  501.         J. Tamburino and as long as I have given you permission to do so.
  502.  
  503.  
  504.         Send all correspondence regarding VGA_FONT to:
  505.  
  506.         Joseph J. Tamburino
  507.         7 Christopher Rd.
  508.         Westford, MA 01886
  509.  
  510.         Phone:               508-692-7756
  511.         Prodigy accnt #:     NWNJ91A
  512.         CompuServe accnt #:  70033,107
  513.  
  514.  
  515.         Above all, enjoy the routines!
  516.  
  517.  
  518.  
  519.  
  520.  
  521.  
  522.  
  523.                                      8
  524.  
  525.  
  526.  
  527.  
  528.  
  529.