home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / QBASIC / VIDBASIC.ZIP / HELP.DOC < prev    next >
Encoding:
Text File  |  1990-11-29  |  48.6 KB  |  977 lines

  1.  
  2. ;Video routine short instruction list
  3.  
  4. ========================================================================
  5.     Copyright (C) Copr. 1990 by Sidney J. Kelly
  6.             All Rights Reserved.
  7.             Sidney J. Kelly
  8.             150 Woodhaven Drive
  9.             Pittsburgh, PA 15228
  10.             home phone 412-561-0950 (7pm to 9:30pm EST)
  11.  
  12.      CompuServ   70043,1656
  13.      Genie       S.KELLY8
  14.  
  15. ========================================================================
  16.  
  17.           The following routines are designed to do something
  18. useful to text without regard to the type of monitor actually
  19. installed.  These routines are text mode primitives.  In most
  20. cases that give you direct control over the hardware in a fashion
  21. that cannot be done except in assembly language.  You can save
  22. the display, write characters or attributes at high speed to the
  23. display, or write to the display using DOS compatible modes to
  24. allow you to use multi-taskers or ANSI.SYS.  You can change text
  25. or attributes on the display.  You can adjust cursor size, turn
  26. off blinking, BLOAD help files, etc.
  27.           These routines are part of a larger freeware library of
  28. QBASIC routines that is currently under construction.  The full
  29. version will be released two days AFTER an OOPS version of QBASIC
  30. is released by MICROSOFT-- at which time few will want to use
  31. these routines.
  32.           Why these were written:
  33.           I originally wrote these routines to parrot Dick Evers
  34. window routines written exclusively in BASIC (You can see his
  35. influence in the demo program).  Then an old issue of PC Magazine
  36. showed how to call MASM video routines from QBASIC, which I think
  37. is based on an earlier BYTE magazine article.  Other PC Magazine
  38. routines, and the discussions about IBM Technical reference video
  39. adapter recognition routines, showed how to identify display
  40. types using just BIOS calls.  Then the quest began: I began my
  41. search of back issues of PC Magazine for programming tidbits, I
  42. bought old assembly language guide books back with the earth was
  43. fresh and the IBM PC with 64kb of memory and two floppies was a
  44. wonder to behold, searched the standard databases for public
  45. domain routines; read more programming books, etc.  The
  46. bibliography at the end of this document should answer your
  47. requests for additional information.
  48.           The video display was selected for improvement because
  49. that is one area a user can really notice the difference between
  50. fast code and slow code.  Some of these routines allow you to do
  51. things that are impossible otherwise.  Other routines allow you
  52. to do something much faster and in an attractive fashion.  All
  53. the routines avoid the agony of using ON ERROR GOTO traps.
  54.           Programmers Assumptions:           These routines are designed to work with MONO, CGA,
  55. HERC, MCGA (mostly color, though generally untested), EGA (mono
  56. or color, 25 or 43 line mode), and VGA (mono or color, 25 or 50
  57. line mode).  In a very limited way, the routines support dual
  58. displays.  These routines assume that the display width is 80
  59. columns wide, mostly because there is no known way to determine
  60. in advance if a particular user's display will support 132 column
  61. mode.  Anyway that is QBASIC's assumption too.  More importantly
  62. I don't own a multi sync display, and I do not access to 10 types
  63. of EGA and 50 types of VGA displays that are necessary to test
  64. everything out on.  Finally, there are several shareware
  65. libraries that already have some of the ATI, Paradise, VESA and
  66. Video Seven EGA/VGA routines built in.  Unfortunately, after
  67. looking at the freeware version of FRACINT (a nifty graphics time
  68. waster that draws fractals), it appears that there are about five
  69. or six different ways to switch displays into high resolution
  70. mode.  Even FRACINT requires the user to select the display type.
  71. (How can I convince my wife that I need a register compatible
  72. 8514/A display and adapter for the ultimate in text mode
  73. displays??????????).
  74.           It is possible to devote many hours to routines for
  75. hardware 95% of the users wont have or need in text mode.  Most
  76. of the direct screen routines use macros that are hard coded for
  77. an 80 column width display. (Lengths of 25, 43, and 50 are
  78. allowed).  This is done for speed in case the poor user only has
  79. a CGA on a PC clone (he needs all the speed he can get).  To show
  80. how it is done, I have included a few routines that actually do
  81. use the BIOS ram data areas to determine the current display
  82. width.
  83.           QBASIC Theory.
  84.           Aside from the current DEF SEG setting, most of QBASIC
  85. video information storage registers are not available inside the
  86. QB.EXE environment, though it is available inside the .EXE
  87. program (which makes testing the routines way too time
  88. consuming).  My routines had to come up with such information
  89. independently.  My solution is store the key variables in the
  90. default data segment in QBASIC (its name in MASM is DGROUP).  To
  91. save space in DGROUP, only 7 bytes of information is kept by the
  92. video routines.  This allows transparent sharing of the
  93. information.  The reason for such "stupid" names (B$V...) for the
  94. DGROUP variables is to only give the MASM routines access to such
  95. information, and prevent normal QBASIC routines (or someone
  96. else's library routines) from messing them up.
  97.           Generally QBASIC only keeps simple variables, (INT,
  98. LONGINT, SINGLE and DOUBLE, and STRINGS) in DGROUP.  Arrays and
  99. TYPE records are usually kept outside DGROUP, with only the
  100. STRING Descriptor or the undocumented Array descriptor kept in
  101. DGROUP.  Thus, the library routines assume that all information
  102. passed from simple variables is information about a near (DGROUP)
  103. address.  If we pass simple integers to MASM routines, and don't
  104. care to have MASM change those variables, we use BYVAL to send
  105. the information to MASM.  If we want to have MASM send
  106. information back about multiple variables, we pass the address
  107. information for the variables without using BYVAL.  If we use arrays, we must use a combination of BYVAL and VARSEG and VARPTR
  108. to get the information we need to manipulate the information
  109. inside the arrays.  VARSEG and VARPTR are necessary because there
  110. is a very great chance that the arrays will be stored as far data
  111. (i.e. not stored in DGROUP).
  112.           Text strings are sent by QBASIC as near address
  113. (relative to DS and DGROUP).  The fist value in the descriptor is
  114. the length of the string.  The second value is the offset address
  115. inside DGROUP.  Fixed length strings are not referenced with
  116. string descriptors.  For that reason, I don't allow such strings
  117. as variables in my routines.
  118.           QBASIC requires that MASM preserve BP, SI, DI, DS, and
  119. keep the direction flag clear (CLD).  All these routines do this.
  120. You will note that MICROSOFT'S CALL INTERRUPT routines do not
  121. save BP (apparently to give you access to some EGA VGA palette
  122. and character font selection routines in the BIOS), and thus will
  123. crash if a critical error occurs.  MICROSOFT offers a replacement
  124. routine, that overcomes this error by preventing any change to
  125. BP.  You should get it if you don't already have it.
  126.           The choice of defining MASM routines as SUB's or
  127. FUNCTION's depends on whether you want to get information from
  128. MASM in DX:AX (the format for FUNCTIONs), or if the MASM routine
  129. either sends back no information or more than one variable (the
  130. format for SUBs).  For simple one variable routines when MASM is
  131. just returning a value, use FUNCTIONs.  To use such functions
  132. inside QBASIC you must either assign the value of the function to
  133. a QBASIC variable or use IF ... THEN statements (C style).  For
  134. everything else use SUBS.
  135.           Note due to an error in the QBASIC parser, always use
  136. the CALL keyword to call the library routines if there is any
  137. chance that you will use a colon as a separator on a line.
  138. Without the CALL keyword, the QBASIC parser assumes that the
  139. routine name followed by a colon is intended as a line label, and
  140. not as a SUB name.  You must use CALL if you will use a SUB that
  141. does not need any parameters and will follow that SUB name by a
  142. colon.
  143.           CGA Theory:
  144.           The CGA is a slow, and sometimes snowy display.  These
  145. routines deal with snow in four ways.  If the CGA is good display
  146. (e.g. COMPAQ, AT&T, or ZENITH) then snow checking can be turned
  147. off automatically.  If a user has a CGA display that does not
  148. display snow (one of many clones, none of which I have access to
  149. or have tested), he can use TOGGLESNOW to turn snow checking off.
  150. The routine can assume the that CGA is snowy and turn off the CGA
  151. for a instant, then turn it back on.  This causes flicker, but I
  152. use when I am changing the entire display.  See BLOADHELP.  The
  153. last alternative is to delay writing words or bytes to the
  154. display until the display is in either vertical or horizontal
  155. retrace mode.  This can be fast (1.5 times as fast as QBASIC's
  156. PRINT routine, while if snow checking is turned off these
  157. routines are 5 to six times faster than QBASIC library routines).
  158. Hardware interrupts are temporarily turned off, so a timer tick
  159. or a keystroke will not upset the counting and writing routines.
  160. The routines generally only allow enough time to read and write one word.  If any further manipulation is required, the wait-for-
  161. retrace loop has to be re-entered a second time.  For speedier
  162. displays (MONO, HERC, EGA, VGA and MCGA), a jump is made to a
  163. faster routine that does not have to wait for retrace.
  164.           There is a fifth way to avoid snow on a CGA, and that
  165. is send one word while the video display is in horizontal retrace
  166. and 400 words while in vertical retrace mode.  However, that was
  167. considered too complicated.  See, Wilton, "Programmer's Guide to
  168. PC & PS/2 Video Systems" (Microsoft 1987).
  169.           Video Theory:
  170.           Video memory in text mode starts at segment &HB000 for
  171. mono displays, and &HB800 for color displays.  The offset of the
  172. first page is 0, then &H1000 (80 x 25) for as many pages as are
  173. allowed.  The screen has no internal divisions representing ROWS
  174. and COLUMNS (except in HERC and CGA graphics modes), it simply is
  175. a logical concept.  At the BIOS/hardware level, for purposes of
  176. displaying a character, the upper left is 0,0 and lower right of
  177. the display in SCREEN 0: WIDTH 80,25  is 24,79.  Thus the
  178. location of a particular word on the display is (Row (0 biased)
  179. times 160 plus Column) times 2.  The 160 is merely 80 columns
  180. times two bytes (character and attribute).  That figure is
  181. hardcoded in my routines so I can use shifts rather than MUL's on
  182. old PC's and speed up the video location MACROS.  On an 8088,
  183. shifts are faster then MUL's (some of the macros show the clocks
  184. for shifts versus MUL's on an 8088 and on an 80286).  When
  185. writing to the display, the attribute is stored (and read into)
  186. in AH, and the character is stored (and read into) in AL.  To
  187. only write characters or attributes, the routines increment DI
  188. (usually) after every write.  This allows certain routines to
  189. write to the display sending only characters or only attributes.
  190.           MASM Theory:
  191.           The MASM routines were designed to be compiled with MS
  192. QUICK ASSEMBLER, using simplified segment names.  They should
  193. compile with MS MASM 5.1 and above.  The DOSSEG keyword might not
  194. be supported in MASM, so use the MASM keyword that arranges the
  195. segments in DOS order, rather than ALPHA order.  If you use TASM
  196. with QUIRKS (IDEAL too?) you should be able to compile these
  197. programs with TASM.  Because A86 does not make MS .OBJ files, you
  198. probably cannot use it.  The same may be true with OPTASM.
  199.           The simplified directives really save time when you
  200. have to identify variables on the stack, and push and pop
  201. variables.  I use the full PROC function and the regular PROC
  202. keywords interchangeably.  Full PROC format is not necessary when
  203. there is no need to address variables on the stack (i.e. no need
  204. to change BP to address the stack) and the QBASIC routine is
  205. described as a FUNCTION.
  206.           The EVEN directive is used to word align loops for
  207. 80286 and 80386 machines.  EVEN inserts NOPS as necessary to word
  208. align loops.  The QBASIC BYVAL directive is used to get
  209. information directly from QBASIC without having to use [BX] or
  210. [SI] to fish out the correct information.  You will note that DS
  211. and OFFSET are used in an unusual way in these routines.  The
  212. string move MASM opcodes use DS:SI (source) to move video bytes
  213. to ES:DI (destination).  We have to wait to set DS to the proper address until we have removed information from the stack, as DS
  214. must point to DGROUP to properly use the stack.  In addition,
  215. OFFSET is faster than LEA to address information in .CODE
  216. segment.  However, for OFFSET to work, MASM must be told that
  217. ASSUME DS:NOTHING, ES:NOTHING.  This makes the offset relative to
  218. beginning of code segment, and not relative to DGROUP (which is
  219. the default if simplified segments are used).  Should anyone have
  220. problems with this, please let me know.   To allow for
  221. compatibility with the 8088 chip, shifts rather than MULs are
  222. used for speed.  I use .code to store most of my variables to
  223. save space in DGROUP, which is comparatively tiny and easily
  224. filed with string data.
  225.           To program in OS/2 .code segment variables are
  226. verbotten, and you must use local variables on the stack.  I
  227. don't have access to the OS/2 DOS compatibility box, so I don't
  228. know how these routines would work under OS/2.  I am certain that
  229. none of these routines would work smoothly under protected mode.
  230.  
  231.  Video routine short instruction list
  232.  ===========================================================================
  233.   DECLARE SUB BACKFILL _
  234.  (BYVAL ULR%, BYVAL ULC%, BYVAL LRR%, BYVAL LRC%, BYVAL ATTRIB%, BYVAL TEXTCHAR%)
  235.   CALL BACKFILL(ULR%, ULC%, LRR%, LRC%, ATTRIB%, TEXT$)
  236.   Description of parameters:
  237.      Because a rectangle can be described by two points, we us the following
  238.      data points:
  239.         ULR Upper left row
  240.         UCL Upper left column
  241.         LRR Lower right row
  242.         LRC Lower right column
  243.         Attribute% = Background color (range 0 to 15) x 16 + Foreground color
  244.             (Range 0 - 15).  The color can be easily described in Hex as &H47
  245.         which yields a red background and white foreground.
  246.         TextChar% = is simply the character code that you want to fill display
  247.         with.  Common characters are 32 or space, 176 - 178 which makes for an
  248.         attractive background character for windowing.
  249.   Fills the display area with a character and a fixed text attribute
  250.  
  251.  ============================================================================
  252.   DECLARE SUB BLOADHELP (FileName$)
  253.   CALL BLOADHELP(FileName$)
  254.  
  255.   Purpose:
  256.           to BLOAD help files without defining size of help file or type of
  257.           display, DEFSEG location, or anything else
  258.  
  259.   Assumes:
  260.           Both BSAVED file and CRT is setup for SCREEN 0, 80 x 25
  261.           Routine does not provide any critical error support.
  262.           Minor file errors will cause abort unless ON ERROR GOTO support
  263.           is provided to handle common errors.
  264.  
  265.           FileName$ must be a near string in DGROUP, cannot be FIXED Length
  266.           or TYPE'd.
  267.  ===========================================================================
  268.   DECLARE SUB CHANGEPAGE ()
  269.   CALL CHANGEPAGE
  270.  Purpose:
  271.          Adjust the current VIDEOSEG to reflect current active page that is set
  272.          by QBASIC.  This routine does not change the page that is currently
  273.          written to, you must use QBASIC to do it.
  274.  
  275.          Also reinitializes Video Data Area
  276.  
  277.  Limit:
  278.          This will permit 25, 43, & 50 line displays
  279.          Note on many HERC's the page size is fixed at 16kb even though
  280.          it really is 4kb in Text Mode.  Because QBASIC does not believe that
  281.          a HERC display has video pages in text mode, this routine ignores
  282.          ignores the possibility of video pages for HERC display.
  283.   Typical page limits in 80 x 25 text mode:
  284.   Mono, HERC    = 0 pages
  285.   CGA           = 4 pages
  286.   EGA (w/128kb) = 8 pages
  287.   VGA           = 8 pages
  288.   With careful tinkering of CODE you could get 32 pages for 256kb EGA/VGA's
  289.   and 8 pages for HERC.  However, QBASIC and PRINT would become all confused.
  290.   That is why this is left to reader to implement.
  291.   Returns:
  292.          Nothing, Video Data Area Filed
  293.  
  294.  ===========================================================================
  295.   DECLARE SUB _
  296.   CLEARAREA (BYVAL ULR%, BYVAL ULC%, BYVAL LRR%, BYVAL LRC%, BYVAL ATTRIB%)
  297.   CALL CLEARAREA (ULR%, ULC%, LRR%, LRC%, ATTRIB%)
  298.   Description of parameters:
  299.      Because a rectangle can be described by two points, we us the following
  300.      data points:
  301.         ULR Upper left row
  302.         UCL Upper left column
  303.         LRR Lower right row
  304.         LRC Lower right column
  305.         Attribute% = Background color (range 0 to 15) x 16 + Foreground color
  306.             (Range 0 - 15).  The color can be easily described in Hex as &H47
  307.         which yields a red background and white foreground.
  308.   Changes the attribute of an area on the screen in text mode
  309.  
  310.  =========================================================================
  311.  DECLARE SUB CLEARSCR (BYVAL ULR%, BYVAL ULC%, BYVAL LRR%, BYVAL LRC%,
  312.  _BYVAL ATTRIB%)
  313.  CALL CLEARSCR(ULR%,  ULC%,  LRR%,  LRC%, ATTRIB%)
  314.        range:   1-50  1-80  1-50   1-80   0-255
  315.   Uses the video bios to scroll a window.
  316.  
  317.  ===========================================================================
  318.   DECLARE SUB CLREOL ()
  319.      CLREOL   Purpose:
  320.         Clears to end of current display line w/o changing attribute
  321.   Assumes:
  322.         80 Column mode, assumes that DI has been set by SETQP; QPRINT;
  323.         QPRINTL; or  QPRNT
  324.  
  325.  ============================================================================
  326.   DECLARE SUB CURSET (Mode%)
  327.   Input:
  328.         Mode = 0  turn off cursor
  329.              NOTE on a VGA with ANSI.SYS installed it might not be possible
  330.              to turn off all attributes of the cursor.
  331.         Mode = 1  turn on normal cursor
  332.         Mode = 2  turn on half block
  333.         Mode = 3  turn on full block
  334.   Returns:
  335.         Nothing
  336.   Purpose:
  337.         Selects attractive cursor sizes over the default QBASIC format.
  338.         Complicated because of need to overcome cursor emulation on VGA/EGA
  339.         With an EGA/VGA if want a full block cursor, cannot rely on cursor
  340.         emulation, must adjust for actual display box (assume 80 x 25).
  341.  
  342.  ============================================================================
  343.   DECLARE FUNCTION DOSPRINT% (BYVAL Row%, BYVAL Col%, Text$)
  344.   IF DOSPRINT% (Row%, Col%, Text$) THEN
  345.       PRINT "Error in text$: null or invalid character"
  346.   END IF
  347.   If you don't need a return code, simply DECLARE as a SUB
  348.  
  349.   Print Text$ at Row%, Column
  350.   Uses DOS Write services to print to STDERR.  STDERR always == CON.
  351.   Does not change the current background attribute, uses whatever was there.
  352.   Only prints to page 0, but no range checks on ROW and COL.  Most useful when
  353.   operating in a multitasking environment or if want to use ANSI.SYS control
  354.   strings.
  355.  
  356.   Returns:
  357.          Error code:
  358.           0 if no error
  359.          -1 if ASCII CHR$(26) found in input stream
  360.  
  361.   Warning:
  362.          Assumes Text$ only contains ASCII text or Carriage return
  363.          control characters.  Any other control characters, e.g. CTRL-C
  364.          will cause Program to terminate, probably destroying file.
  365.          Routine checks for C/R, CTRL-C, CTRL-S, CTRL-P after each character
  366.          If don't want this character checking, use DMPRINT
  367.  
  368.   Notes:
  369.   Moves the cursor to the beginning of the string.  However does not tell
  370.   QBASIC the current cursor location.  Should be a well managed function
  371.   under WINDOWS or other multitasker.
  372.  ============================================================================
  373.   DECLARE FUNCTION DMPRINT% (BYVAL Row%, BYVAL Col%, Text$)
  374.   IF DMPRINT% (Row%, Col%, Text$) THEN
  375.       PRINT "Error in text$: null or invalid character"
  376.   END IF
  377.  
  378.   If you don't need a return code, simply DECLARE as a SUB
  379.  
  380.   Uses DOS Write services to print to STDERR.  STDERR always == CON.
  381.   Does not change the current background attribute, uses whatever was there.
  382.   Only prints to page 0, but no range checks on ROW and COL.
  383.   Returns:
  384.          Error code:
  385.           0 if no error
  386.          -1 if CON error.
  387.   If you don't need a return code, simply DECLARE as a SUB
  388.  
  389.   Warning:
  390.          Ignores any control characters, merely prints string.
  391.  
  392.   Notes:
  393.   Moves the cursor to the beginning of the string.  However does not tell
  394.   QBASIC the current cursor location.  Should be a well managed function
  395.   under WINDOWS or other multitasker.
  396.  
  397.   Routine is about 1.23 times faster than DOSPRINT on an EGA
  398.  
  399.  =======================================================================
  400.  DECLARE FUNCTION DSPATTRIB% (BYVAL Foreground%, BYVAL Background%)
  401.  Takes Background color x 16 plus Foreground color
  402.  to make an attribute used by the system routines
  403.  allows Background% > 15, so can blink
  404.  This routine is not necessary, it just makes life easier for the programmer
  405.  who remembers the format for COLOR.
  406.  
  407.  ============================================================================
  408.   DECLARE FUNCTION DUALDISPLAY% ()
  409.   Returns:
  410.         True  (<> 0)  if two displays found
  411.         False (0)     if only one CRT found
  412.  
  413.  ============================================================================
  414.   DECLARE EGAMONO (BYVAL Mode%)
  415.   CALL EGAMONO (Mode%)
  416.   Purpose:
  417.         Forces VGA/EGA mono display to normal MONO attributes
  418.         This allows programmer to have the same attributes appear on a
  419.         HERC, MONO, or EGA Mono Display
  420.   Input:
  421.         Mode%  = 0 if want default mono attributes
  422.         Mode% <> 0 if want Herc type attributes
  423.   Returns: Nothing
  424.  
  425.   Limitations:          For contrast, colors can only be used against White or Intense.
  426.          Primary colors appear as Black.
  427.          Only White or Intense can be contrasted against Black.
  428.          Blue and Intense Blue attributes are not underlined, unlike HERC/MONO
  429.          All intense colors appear as white.
  430.   Full control over VGA is not possible because of GRAY scaling and large
  431.   number of DAC/palette registers.  To get control over those two features would
  432.   make the program much larger.
  433.   Tinkering required for mono MCGA, but who has one of those?
  434.  
  435.  ============================================================================
  436.   DECLARE SUB FADE ()
  437.   CALL FADE
  438.   Purpose: Clever visual effect, fades out display to white on black.
  439.   Changes all characters to spaces.
  440.   Works in TextMode only.  Sensitive to all video modes (i.e. no snow on CGA's)
  441.   Assumes: Display width is 80 x 25, 80 x 43 or 80 x 50
  442.  
  443.  ============================================================================
  444.   DECLARE FUNCTION FINDCOLOR% ()
  445.   Returns:
  446.         True  (<> 0)  if color CRT found, even if not active
  447.         False (0)     if color CRT not found
  448.  
  449.  ============================================================================
  450.   DECLARE FUNCTION FINDMONO% ()
  451.   Returns:
  452.         True  (<> 0)  if mono CRT found, even if not active
  453.         False (0)     if mono CRT not found
  454.  
  455.  ============================================================================
  456.   DECLARE SUB HERCMODE (BYVAL Mode%)
  457.   CALL HERCMODE (Mode%)
  458.   Purpose is a to control dual displays with color and HERC
  459.  
  460.   Input:
  461.         Mode =  0, Sets a Herc display to half-mode, so it can use a CGA
  462.         Mode <> 0, Sets a Herc display to full-mode, can not use a CGA
  463.   Does not test for existence of Herc display.
  464.  
  465.  =======================================================================
  466.   DECLARE FUNCTION INCOLOR%()
  467.         IF INCOLOR% THEN
  468.             ... etc.
  469.   Tests if have a color or mono display attached.  Test primary display only.
  470.   returns          -1 if color display (may be a single color display)
  471.                     0 if BW mono display
  472.   Note will not be fooled by Herc CGA emulation routines.  Doesn't test
  473.   for single color displays like COMPAQ, AT&T
  474.  
  475.  =======================================================================
  476.   DECLARE SUB LSCROLL (BYVAL Attribute%)
  477.   CALL LSCROLL(Attribute%)
  478.   Scrolls screen left   Mostly for fun.  To be really useful would have to set it up for windows
  479.   and would have to print using VPRINT.
  480.   Designed to handle an 80 x 25 text display
  481.  
  482.  ============================================================================
  483.  DECLARE SUB MAKEBOXES _
  484.  (BYVAL ULR%, BYVAL ULC%, BYVAL LRR%, BYVAL LRC%, BYVAL HASNO%, BYVAL BORDER%,_
  485.   BYVAL ATTRIB%)
  486.  CALL MAKEBOXES(ULR,ULC,LRR,LRC,HASHNO,BORDER,ATTRIB)
  487.  
  488.   Description of parameters:
  489.      Because a rectangle can be described by two points, we us the following
  490.      data points:
  491.         ULR = Upper left row
  492.         UCL = Upper left column
  493.         LRR = Lower right row
  494.         LRC = Lower right column
  495.  
  496.         HashNo% = is simply the character code that you want to fill display
  497.         with.  Common characters are 32 or space, 176 - 178 which makes for an
  498.         attractive background character for windowing.
  499.  
  500.         Border = Select border type:
  501.            0 = no border
  502.            2 = single sided
  503.            3 = single vertical, double horizontal
  504.            4 = double vertical, single horizontal
  505.            5 = solid box
  506.            Default or 1 = double vertical, double horizontal
  507.  
  508.         Add 256 to BORDER if want shadows.  Shadow designed for 80 x 25 windows,
  509.         to prevent page overlap.  Shadow color is White on blue background for
  510.         a mono display, is white on black background
  511.  
  512.         Attribute% = Background color (range 0 to 15) x 16 + Foreground color
  513.             (Range 0 - 15).  The color can be easily described in Hex as &H47
  514.         which yields a red background and white foreground.
  515.  
  516.   Somewhat shorter and 1.0076 times faster than using the primitives
  517.   in this .OBJ file to do the same thing
  518.  
  519.  ============================================================================
  520.   DECLARE SUB QATTRIB (BYVAL ROW%, BYVAL COL%, BYVAL NUMCHAR%, BYVAL ATTRIB%)
  521.   Row, Column is the starting location. attribute is the color
  522.   and Numchar is the number of characters to change.
  523.   Changes the attribute of characters on the screen in text mode
  524.   Assumes: Display width is 80 columns, Rows are 25, 43, or 50
  525.  
  526.  ============================================================================
  527.   QPRINT.ASM - performs Quick Printing in the QuickBASIC
  528.   DECLARE SUB QPRINT (BYVAL ROW%, BYVAL COL%, Text$, BYVAL ATTRIBUTE%)
  529.   Works in TextMode only, ignores all special characters
  530.   Sensitive to all video modes (i.e. no snow on CGA's)
  531.   If no attribute is selected, the default attribute is &H07 (normal)   Assumes: Display width is 80 columns, Rows are 25, 43, or 50
  532.  
  533.  ===========================================================================
  534.   DECLARE SUB QPRINTL (Text$)
  535.           CALL QPRINTL(Text$)
  536.   Usage: CALL SETQP(ROW%, COLL%, Attribute%) the first time to set
  537.   the defaults to current display size.  Then QPRINTL on down the display.
  538.   You should use SETQP to start, since scroll routine needs the proper
  539.   attribute to scroll the screen up.
  540.  
  541.   Purpose:
  542.           To work similarly to PRINT Text$
  543.  
  544.           Major differences are:
  545.           a)  Assumes that a VIEW PRINT has been executed
  546.           b)  will not parse the Text$ and start a new line if length of
  547.             Text$ is longer than remaining space on current line.  PRINT
  548.             is designed for formatted column printing, while this
  549.             routine is not.
  550.           c) if at Last Row, Column 80, QPRINTL will scroll the display
  551.              can't stop it.
  552.  
  553.   Speed:
  554.         Varies with length of Text$ and length of display
  555.           for a color EGA on a 10 Mhz AT, the speed varies from 3% faster
  556.           (if LEN(Text$) = 80) to 48% faster.
  557.           Typical speed increase is 12%
  558.  
  559.  ============================================================================
  560.   QPRT.ASM - performs Quick Printing in the QuickBASIC
  561.   DECLARE SUB QPRT (BYVAL ROW%, BYVAL COL%, TEXT$)
  562.   Works in TextMode only, ignores all special characters
  563.   Sensitive to all video modes (i.e. no snow on CGA's)
  564.   Does not change the attribute, uses whatever was there.
  565.   Much faster than LOCATE X,Y : PRINT T$
  566.   Routine is about 6   times faster than PRINT on a color EGA on an AT
  567.              about 4.5 times faster than PRINT on a color VGA on a 386SX
  568.              about 7   times faster than PRINT on a mono EGA on an AT
  569.              about 1.5 to 2 times faster than PRINT on a CGA on an IBM PC
  570.              about 5   times faster than PRINT on a HERC on an AT
  571.              about 6   times faster than PRINT on a COMPAQ Portable
  572.  
  573.   Assumes: Display width is 80 columns, Max Rows are 25, 43, or 50
  574.  
  575.  ============================================================================
  576.   DECLARE SUB RECOLOR (BYVAL OrigColor%, BYVAL NewColor%)
  577.   CALL RECOLOR( OrigColor%, NewColor%)
  578.   Purposes: Change one specific color to another without upsetting the display
  579.   or using palette registers (which couldn't be restored easily using an EGA)
  580.  
  581.   Color is written as BackGround x 16 + ForeGround color
  582.  
  583.   Sensitive to all video modes (i.e. no snow on CGA's)
  584.   Assumes: Display width is 80 x 25, 80 x 43 or 80 x 50
  585.  ========================================================================
  586.  RESTSCRN.ASM - restores 80 x 25 page text screen in QuickBASIC array
  587.  Parameters:
  588.   DECLARE SUB RESTSCRN (BYVAL Segment%, BYVAL Offset%)
  589.   DIM ARRAY%(2000)
  590.   CALL RESTSCRN(VARSEG(ARRAY%(0)), VARPTR(ARRAY%(0)))
  591.   To save display call SAVESCRN
  592.  
  593.  =======================================================================
  594.   DECLARE SUB RSCROLL (BYVAL Attribute%)
  595.   CALL RSCROLL(Attribute%)
  596.   Scrolls screen right
  597.   Mostly for fun.  To be really useful would have to set it up for windows
  598.   and would have to print using VPRINT.
  599.   Designed to handle an 80 x 25 text display
  600.  
  601.  ========================================================================
  602.  SAVESCRN.ASM - saves 80 x 25 text screen page in QuickBASIC array
  603.  Parameters:
  604.   DECLARE SUB SAVESCRN (BYVAL Segment%, BYVAL Offset%)
  605.   DIM ARRAY%(2000)
  606.   CALL SAVESCRN( VARSEG(ARRAY%(0)), VARPTR(ARRAY%(0)))
  607.   To restore call RESTSCRN
  608.  
  609.  ===========================================================================
  610.  DECLARE FUNCTION S2BUFF  ;put text screen in buffer
  611.  DECLARE FUNCTION BUFF2S  ;get text screen from buffer
  612.  
  613.  Allows movement of text screens, page 0 to and from a buffer.
  614.  Modified to handle a CGA display so will NOT cause SNOW on a CGA
  615.  
  616.  Handles  80 x 25, 80 x 43, and 80 x 50 displays.  Checks current status each
  617.  time it makes a shift.
  618.  
  619.  Storage in Code Segment used to save space in DGROUP, makes DATA near
  620.  without using up the limited amount of DGROUP space.  However prevents
  621.  use of program in OS/2 which prohibits any change to CodeSeg values.
  622.  
  623.  ===========================================================================
  624.  DECLARE SUB SCN2BUFF ()  ;put text screen in buffer
  625.  DECLARE SUB BUFF2SCN () ;get text screen from buffer
  626.  
  627.   Allows movement of text screens, page 0 to and from a buffer.
  628.   Modified to handle a CGA display so will NOT cause SNOW on a CGA
  629.  
  630.   Handles only 80 x 25 displays. Will not crash on 80 x 43 or 80 x 50 just wont
  631.         save the entire display.  See S2BUFF if want larger displays.
  632.  
  633.   Storage in Code Segment used to save space in DGROUP, makes DATA near
  634.   without using up the limited amount of DGROUP space.  However prevents
  635.   use of program in OS/2 which prohibits any change to CodeSeg values.
  636.  
  637.  =========================================================================  DECLARE SUB SCROLLDOWN (BYVAL ULR%, BYVAL ULC%, BYVAL LRR%, BYVAL LRC%, BYVAL
  638.  _ ROWS%, BYVAL ATTRIB%)
  639.  CALL SCROLLDOWN(ULR%, ULC%, LRR%, LRC%, ROWS%, ATTRIB%)
  640.   If ROWS%=0 then entire window cleared
  641.   Description of parameters:
  642.      Because a rectangle can be described by two points, we us the following
  643.      data points:
  644.         ULR = Upper left row
  645.         UCL = Upper left column
  646.         LRR = Lower right row
  647.         LRC = Lower right column
  648.         Rows = number of rows to scroll
  649.   Uses the video bios to scroll a window.
  650.  
  651.  =========================================================================
  652.  DECLARE SUB SCROLLUP (BYVAL ULR%, BYVAL ULC%, BYVAL LRR%, BYVAL LRC%, BYVAL
  653.  _ ROWS%, BYVAL ATTRIB%)
  654.  CALL SCROLLUP(ULR%, ULC%, LRR%, LRC%, ROWS%, ATTRIB%)
  655.   If ROWS%=0 then entire window cleared
  656.   Description of parameters:
  657.      Because a rectangle can be described by two points, we us the following
  658.      data points:
  659.         ULR = Upper left row
  660.         UCL = Upper left column
  661.         LRR = Lower right row
  662.         LRC = Lower right column
  663.         Rows = number of rows to scroll
  664.   Uses the video bios to scroll a window.
  665.  
  666.  ===========================================================================
  667.   DECLARE SUB SETQP (BYVAL ROW%, BYVAL COLL%, BYVAL Attribute%)
  668.           CALL SETQP(ROW%, COLL%, Attribute%)
  669.   Purpose:
  670.           Initializes varibles, and sets DI to target address.  This is the
  671.   initialization routine for QPRINTL.  Selects the attribute used to scroll
  672.   the display upward.
  673.   Assumes that user wants to set page size to full size of current dsplay
  674.   such as 80 x 25, 80 x 43, or 80 x 50
  675.  
  676.  ===========================================================================
  677.   DECLARE SUB SETBLINK (BYVAL Status%)
  678.   CALL SETBLICK (Status%)
  679.   Purpose:
  680.         Toggles background blinking/intensity for MONO, CGA, EGA, VGA
  681.         allows use of background colors that would otherwise flash
  682.   Parameters:
  683.         =  0 turn off blinking, enable intensity
  684.         <> 0 to turn it on again
  685.   Returns:
  686.         nothing
  687.  
  688.  ===========================================================================
  689.   DECLARE SUB SNOWCHECK ()
  690.   CALL SNOWCHECK   Purpose:
  691.          Clears the snowcheck variable (B$DVIDEOPORT) if it finds a CGA
  692.          display by OLIVETTI (AT&T), COMPAQ, or ZENITH
  693.  
  694.   Returns:
  695.          Nothing DGROUP Data Area Filed
  696.  
  697.  ============================================================================
  698.   DECLARE SUB SWAPCOLOR ()
  699.   CALL SWAPCOLOR
  700.   Purpose:
  701.           If have a CGA and a MONO display, this makes the CGA active
  702.   Note:
  703.           Does not test if have either CGA or MONO installed
  704.   See the FIND routines
  705.   Side Effect: Display Cleared
  706.  
  707.  ============================================================================
  708.   DECLARE SUB SWAPMONO ()
  709.   CALL SWAPMONO
  710.   Purpose:
  711.           If have a CGA and a MONO display, this makes the MONO active
  712.   Note:
  713.           Does not test if have either CGA or MONO installed
  714.   See the FIND routines
  715.   Side Effect: Display Cleared.  If have dual displays, the mono display is put
  716.         in HERC half mode for CGA compatibility purposes.   Feedback please!
  717.  
  718.  ===========================================================================
  719.   DECLARE SUB TOGGLESNOW (Mode%)
  720.   CALL TOGGLESNOW(Mode%)
  721.  Input: If Mode% =  0, clears SNOWCHECK
  722.         If Mode% <> 0, leaves SNOWCHECK set
  723.  Purpose:
  724.          Clears the snowcheck variable (B$DVIDEOPORT) if find a CGA display
  725.          Also reinitializes Video Data Area
  726.  
  727.  Returns:  Nothing
  728.            Video Data Area Filed
  729.  
  730.  ===========================================================================
  731.   DECLARE SUB VADDR (Row%, Column%)
  732.    CALL VADDR(Row%, Column%)
  733.    returns the current end of string address for the qprint routines
  734.  
  735.  ============================================================================
  736.   DECLARE SUB VIDINFO (MODE%, ROW%, COLUMN%, CURPAGE%, PAGESIZE%)
  737.   CALL VIDINFO(MODE%, ROW%, COLUMN%, CURPAGE%, PAGESIZE%)
  738.   Purpose:
  739.         Returns information about current video display status.
  740.         Mode%     = current video mode using BIOS format
  741.         Row%      = number of rows currently being displayed
  742.         Cols%     = width of display in columns
  743.         Curpage%  = currently active page         Pagesize% = size of current page in bytes, default is 4kb
  744.                     for an 80 x 25 display.
  745.   Note:
  746.         PAGESIZE% on many HERC clones will be incorrect and reflect the
  747.   information of the HERC display in HALF mode or 16kb size.
  748.   Routine will store correct Row% length in BIOS ram for CGA, HERC & MONO
  749.  
  750.  ===========================================================================
  751.   DECLARE FUNCTION VIDEOSTAT% ()
  752.  
  753.   VideoStatus Analyzer
  754.   Program returns video information for use by QBASIC
  755.   returns highest level of SCREEN mode supported by the Hardware.
  756.   Returns information about the PRIMARY display only
  757.   This routine with a SELECT CASE, can tell you how many display pages
  758.   are available in text mode, SCREEN 0: WIDTH 80,25
  759.   VGA has 8 pages (0 to 7)
  760.   EGA with > 64kb has 8 pages (0 to 7)
  761.   EGA with 64kb has 4 pages (0 to 3)
  762.   CGA has 4 pages (0 to 3)
  763.   MONO has 1 pages (0)
  764.   HERC has 1 page in SCREEN 0 (0), 2 pages in SCREEN 3 (0 to 1)
  765.  
  766.   Exceptions:
  767.   MCGA color returns a mode 11, so can contrast w/ VGA
  768.   HERC w/o MSHERC.COM reports a -3 so you can tell user to correct matters
  769.   COMPAQ with CGA reports -2 so can force use of monchrome attributes.
  770.   EGA's with CGA displays report -8 if have only 64kb of memory
  771.   EGA's with ECD display report  8 if have only 64kb of memory
  772.  
  773.   Returns:
  774.   Mono         =   0
  775.   CGA          =   2
  776.   PGA          =   2   (Untested, assume PGA would be treated as CGA)
  777.   COMPAQ - CGA =  -2   to tell that user may have a single color display
  778.   HERC         =   3   if have HERC and MSHERC.COM
  779.   HERC         =  -3   if have HERC but w/o MSHERC.COM
  780.   AT&T         =   4,  but only if have just CGA display, not EGA or VGA
  781.       Microsoft QuickC/C makes Olivetti EGA and VGA return a separate code.
  782.       I don't know why anyone would care if the EGA/VGA emulation were
  783.       good.
  784.   EGA64        =   8   Because resolution limited for 64k EGA
  785.   EGA64 w/CGA  =  -8   Because resolution limited to CGA modes
  786.   EGA          =   9   Have minimum of 128kb of video ram
  787.   EGA w/CGA    =  -9   Since resolution limited to CGA modes
  788.   MCGA         =  11   If have an analog color display
  789.   MCGA         = -11   If have an EGA ECD digital color display, since
  790.                        resolution of this display is limited to EGA modes
  791.   VGA          =  13
  792.   EGA/VGA mono =  10   I guess will catch MCGA mono too
  793.  
  794.   The above numbering routine was selected so if the programmer put ABS in
  795. front of the returned value, a SCREEN command could be entered.  The other
  796. advantage was that the routines are much faster thant the ON ERROR GOTO traps using ERR 5 to determine what is allowed and what is not.
  797.  
  798.   Version 0.92
  799.  
  800.   Tested:     CGA clone, HERC clone, EGA mono, EGA color, VGA color, COMPAQ CGA,
  801.               VGA clone, EGA clone (Paradise clone, ATI EGA Wonder), AT&T 6300
  802.   Not tested: PGA, VGA monochrome, MCGA (color or monochrome)
  803.  
  804.  ===========================================================================
  805.   VPRINT.ASM - performs Vertical Printing in the QuickBASIC
  806.   DECLARE SUB VPRINT (BYVAL ROW%, BYVAL COL%, Text$, BYVAL ATTRIBUTE%)
  807.   Works in TextMode only, ignores all special characters
  808.   Sensitive to all video modes (i.e. no snow on CGA's)
  809.   If no attribute is selected, the default attribute is &H07 (normal)
  810.   Assumes: Display width is 80 columns
  811.  
  812.  ============================================================================
  813.   VPRT.ASM - performs Vertical Printing in the QuickBASIC
  814.   DECLARE SUB VPRT (BYVAL ROW%, BYVAL COL%, TEXT$)
  815.   Works in TextMode only, ignores all special characters
  816.   Sensitive to all video modes (i.e. no snow on CGA's)
  817.   Does not change the attribute, uses whatever was there.
  818.   Assumes: Display width is 80 columns
  819.  
  820.  ==============================================================================
  821.      WINDREST.ASM - restores a portion of the text screen in QuickBASIC;
  822.  
  823.   DECLARE SUB WINDREST(BYVAL ULR%,BYVAL ULC%,BYVAL LRR%,BYVAL LRC%,
  824.  _BYVAL SEGADD%, BYVAL OFFADR% )
  825.   CALL  WINDREST(ULR%,ULC%,LRR%,LRC%,VARSEG(STORAGE(0)),VARPTR(STORAGE(0)))
  826.   Description of parameters:
  827.      Because a rectangle can be described by two points, we us the following
  828.      data points:
  829.         ULR = Upper left row
  830.         UCL = Upper left column
  831.         LRR = Lower right row
  832.         LRC = Lower right column
  833.      Dimension storage array to handle size of display in bytes
  834.     E.g. 80 x 20 display would require an integer array of 1600
  835.  
  836.  ===============================================================================
  837.      WINDSAVE.ASM - saves a portion of the text screen in QuickBASIC
  838.   call from Quickbasic:
  839.   DECLARE SUB WINDSAVE(BYVAL ULR%,BYVAL ULC%,BYVAL LRR%,BYVAL LRC%,
  840.  _BYVAL SEGADD%, BYVAL OFFADR% )
  841.   DIM STORAGE(2000)
  842.   CALL  WINDSAVE(ULR%,ULC%,LRR%,LRC%,VARSEG(STORAGE(0)),VARPTR(STORAGE(0)))
  843.  
  844.   Description of parameters:
  845.      Because a rectangle can be described by two points, we us the following
  846.      data points:
  847.         ULR = Upper left row
  848.         UCL = Upper left column
  849.         LRR = Lower right row         LRC = Lower right column
  850.      Dimension storage array to handle size of display in bytes
  851.     E.g. 80 x 20 display would require an integer array of 1600
  852.  
  853.  ===============================================================================
  854.  
  855. Acknowledgments:
  856.         Most of my deeper insight into video programming came from a set of
  857. public domain TASM video routines by Dave Bennett, (with the Toad Halls
  858. tweaks), from 1988.  He is the source of the routine for using both the
  859. horizontal and vertical retrace to write to a CGA.  In addition, his code
  860. showed the simple techniques used to write just characters and just attributes
  861. to the display.
  862.  
  863. Author  : Dave Bennett
  864. Version : 1.0
  865. Date    : 11/9/88
  866. CIS PPN : 74635,1671
  867.  
  868. Bibliography:
  869.         General DOS/BIOS routines:  Ray Duncan and Peter Norton's programming
  870. books.  If you can only afford one book, get Duncan's.  Duncan, "Advanced MS-
  871. DOS Programming" (2d Ed. Microsoft 1988).  Very easy to read and to refer to
  872. specific routines.  The text is very well formatted for easy reference.
  873.         Norton, "The New Peter Norton Programmer's Guide to the IBM PC and
  874. PS/2" (Harper & Row 1988).  A book designed to help you visualize what is
  875. going on.  Having been "burned" by writing a book on the PC Junior, and
  876. experienced the agony of hardware incompatibilities in writing the Norton
  877. Utilities, Peter wants everybody to use the bios and documented DOS routines.
  878.         EGA/VGA Programming:
  879.         Michael Abrash, "Power Graphics Programming" (Que 1990).  Excellent
  880. reprint of Programmer's Journal (Buy this magazine!) columns.  Does not cover
  881. Super VGA and beyond (that is being done now in the Programmer's Journal).
  882. Mostly useful for graphics routines.  The best book on the subject, and the
  883. only technical book that one could actually enjoy reading as a book rather
  884. than as a reference.  See also various issues of PC Magazine for programming
  885. tidbits.
  886.         Ferro, "Programmer's Guide to the EGA and VGA Cards," (Addison-Wesley
  887. 1988).   Good, but slightly disorganized.  The only book that discusses the
  888. registers (unfortunately more in the nature of a dictionary rather than in
  889. examples of how to manipulate the registers).  A good list of typical bios
  890. defaults, which are important for the EGA since you can't read the registers.
  891.         Herc:
  892.         Doty, "Programmer's Guide to Hercules Graphics Cards" (Addison-Wesley
  893. 1988).  Good book on the subject.  Describes the high end Herc systems.  Many
  894. programming examples and port descriptions.
  895.         Herc, CGA, EGA, VGA:
  896.         Wilton, "Programmer's Guide to PC & PS/2 Video Systems" (Microsoft
  897. 1987).  Excellent general purpose book.  Said to have some errors, though I
  898. have found nothing more than a few typos.  Does not cover Super VGA and
  899. beyond.  Partial information is set forth in Phoenix's "System Bios for
  900. PC/XT/AT Computers and Compatibles" (Addison-Wesley 1989).
  901.         MONO and CGA:
  902.         Bradley, "Assembly Language Programming for the IBM Personal
  903. Computers" (Prentice Hall 1984).  Good technical descriptions of the original PC.  Only book I have seen that has really shown how to switch displays,
  904. manipulate DMA, make sound, and manipulate floppy disk drives at the PORT
  905. level (teaches you why we have BIOS and DOS routines).  Good book on the 8087.
  906. Probably now out of print.  I bought my copy at a book store that sells
  907. remainders.
  908.         DOS Programming:
  909.         Detteman, "DOS Programmer's Reference (2d Ed. Que 1989).  Excellent
  910. book with a very helpful look at undocumented DOS.  Doesn't preach about not
  911. using undocumented DOS as does Peter Norton.
  912.         Waite Group "Dos Developer's Guide" (2d Ed Sams 1989).  Good book on
  913. Expanded memory and math chips.  Several good discussions of the undocumented
  914. DOS functions.  Such a big book, that you feel you got your money's worth
  915. based just on weight.
  916.         General Programming:
  917.         Holzner, "PS/2-PC Assembly Language"  (Brady 1989)  Good introduction
  918. to assembly language programming.  In many respects better than Holzner,
  919. "Advanced Assembly Language on the IBM PC" (Brady 1987).
  920.         Tischer, "PC System Programming for Developers" (ABACUS 1989).  Good
  921. technical survey of PC/AT systems.  Comes with a lot of programs showing how
  922. to do useful things in MASM, QBASIC, PASCAL and C.  The only shortcoming is
  923. that the book is printed on very cheap paper.  One of the few books to show
  924. register usage of DOS and BIOS routines (important so you can save variables
  925. in registers rather than in memory or pushed on the stack.)  Doesn't discuss
  926. DOS Version 4 in an integrated fashion.  Such a big book, that you feel you
  927. got your money's worth based just on weight.
  928.         Young, "Inside DOS: A Programmer's Guide", (Sybex 1990).  Good source
  929. of MASM code, with a primary emphasis on C (The MASM code is similar for both
  930. C and QBASIC).  A reprint of "MS DOS Advanced Programming" (Sybex 1988).  (I
  931. didn't discover this until I purchased both).
  932.         Wyatt, "Using Assembly Language" (2d Ed. QUE 1989).  Some decent video
  933. routines.  No useful description of VGA.  EGA routines are primitive.  Good
  934. insight into programming for high level languages.  Complete listing of all
  935. the Intel keywords, but reads too much like an Intel-English disctionary.
  936. Most of the examples in the keyword section are not really helpful and the
  937. ASCII math routines are not well described.  One major programming feature
  938. dropped from the 1st edition was the AT keyboard programming routines.  Does
  939. this mean AT keyboards are only marginally compatible on the hardware level?
  940. Feedback please.
  941.         QBASIC Programming:
  942.         Goodwin, "QuickBASIC Advanced Programming Tools" (MIS 1989).  A much
  943. better book for QBASIC code (sorting, popup windows, dropdown windows and
  944. menubar programs) than for MASM code.  The MASM code relies on video bios to
  945. do things (which is slow, though always compatible).  Moreover, screens are
  946. stored in STRINGs rather than arrays, which greatly limits the usefulness of
  947. his MASM routines.  (I agree storing screens in arrays takes more work).  A
  948. programmer can have access to several hundred KB of far data in arrays, while
  949. he can only have access to 30 to 40kb of precious string space in DGROUP.
  950.         Lesser,  "Advanced Quickbasic 4.0 Language Extensions with Modular
  951. Tools" (Bantam 1988).  This is how I learned about MASM/QBASIC programming.
  952. Talks more about ideas that were important for QBASIC Version 3.0/MASM pre-
  953. version 5.1  (before simplified directives) than for QBASIC Version 4.x.
  954. BELIEVES in structured programming.  Not too many hardware insights.  Offers
  955. generally sound advice.         Shammas, "QuickBASIC- Programming Techniques and Library Development"
  956. (M&T Publishing 1988).  Good QBASIC code.  Some of the string routines are
  957. fast.  He has some BTREE and high level math routines.
  958.         Books Not Recommended (How daring!):
  959.         Murray & Pappas, "80386/80286 Assembly Language Programming"
  960. (Osborne/McGraw Hill 1986).  Only feature of the book is a list of clock
  961. cycles for 80286/80386 opcodes.  Reads like an Intel-English dictionary.
  962.         Duntemann, "Assembly Language from Square One" (Scott, Foresman 1990)
  963. Designed for the beginning programmer.  Suffers from a serious case of
  964. excessive cuteness.  See game of "Big Bux", page 8.  PC Techniques (a good
  965. programming magazine, like those HAX) shows he is capable of much, much more.
  966.  
  967. What's next:
  968.         Two more freeware QBASIC libraries will be released: a) Mouse and
  969. Keyboard routines; and b) DOS and Equipment ID routines.  All will include
  970. MASM source and .OBJ code.  If I get any significant feedback, I might even
  971. release revised libraries.
  972.         I think once you are finished using these libraries you will discover
  973. that programming is much like fishing.  At first, you just go fishing, then
  974. you want to catch big fish.  After a while, you become content to merely catch
  975. fish with whatever is fast, cheap and handy.
  976.         Oh yes, I almost forgot, in case you are wondering, I am a tax lawyer
  977. trying to "catch big fish"