home *** CD-ROM | disk | FTP | other *** search
-
- ;Video routine short instruction list
-
- ========================================================================
- Copyright (C) Copr. 1990 by Sidney J. Kelly
- All Rights Reserved.
- Sidney J. Kelly
- 150 Woodhaven Drive
- Pittsburgh, PA 15228
- home phone 412-561-0950 (7pm to 9:30pm EST)
-
- CompuServ 70043,1656
- Genie S.KELLY8
-
- ========================================================================
-
- The following routines are designed to do something
- useful to text without regard to the type of monitor actually
- installed. These routines are text mode primitives. In most
- cases that give you direct control over the hardware in a fashion
- that cannot be done except in assembly language. You can save
- the display, write characters or attributes at high speed to the
- display, or write to the display using DOS compatible modes to
- allow you to use multi-taskers or ANSI.SYS. You can change text
- or attributes on the display. You can adjust cursor size, turn
- off blinking, BLOAD help files, etc.
- These routines are part of a larger freeware library of
- QBASIC routines that is currently under construction. The full
- version will be released two days AFTER an OOPS version of QBASIC
- is released by MICROSOFT-- at which time few will want to use
- these routines.
- Why these were written:
- I originally wrote these routines to parrot Dick Evers
- window routines written exclusively in BASIC (You can see his
- influence in the demo program). Then an old issue of PC Magazine
- showed how to call MASM video routines from QBASIC, which I think
- is based on an earlier BYTE magazine article. Other PC Magazine
- routines, and the discussions about IBM Technical reference video
- adapter recognition routines, showed how to identify display
- types using just BIOS calls. Then the quest began: I began my
- search of back issues of PC Magazine for programming tidbits, I
- bought old assembly language guide books back with the earth was
- fresh and the IBM PC with 64kb of memory and two floppies was a
- wonder to behold, searched the standard databases for public
- domain routines; read more programming books, etc. The
- bibliography at the end of this document should answer your
- requests for additional information.
- The video display was selected for improvement because
- that is one area a user can really notice the difference between
- fast code and slow code. Some of these routines allow you to do
- things that are impossible otherwise. Other routines allow you
- to do something much faster and in an attractive fashion. All
- the routines avoid the agony of using ON ERROR GOTO traps.
- Programmers Assumptions: These routines are designed to work with MONO, CGA,
- HERC, MCGA (mostly color, though generally untested), EGA (mono
- or color, 25 or 43 line mode), and VGA (mono or color, 25 or 50
- line mode). In a very limited way, the routines support dual
- displays. These routines assume that the display width is 80
- columns wide, mostly because there is no known way to determine
- in advance if a particular user's display will support 132 column
- mode. Anyway that is QBASIC's assumption too. More importantly
- I don't own a multi sync display, and I do not access to 10 types
- of EGA and 50 types of VGA displays that are necessary to test
- everything out on. Finally, there are several shareware
- libraries that already have some of the ATI, Paradise, VESA and
- Video Seven EGA/VGA routines built in. Unfortunately, after
- looking at the freeware version of FRACINT (a nifty graphics time
- waster that draws fractals), it appears that there are about five
- or six different ways to switch displays into high resolution
- mode. Even FRACINT requires the user to select the display type.
- (How can I convince my wife that I need a register compatible
- 8514/A display and adapter for the ultimate in text mode
- displays??????????).
- It is possible to devote many hours to routines for
- hardware 95% of the users wont have or need in text mode. Most
- of the direct screen routines use macros that are hard coded for
- an 80 column width display. (Lengths of 25, 43, and 50 are
- allowed). This is done for speed in case the poor user only has
- a CGA on a PC clone (he needs all the speed he can get). To show
- how it is done, I have included a few routines that actually do
- use the BIOS ram data areas to determine the current display
- width.
- QBASIC Theory.
- Aside from the current DEF SEG setting, most of QBASIC
- video information storage registers are not available inside the
- QB.EXE environment, though it is available inside the .EXE
- program (which makes testing the routines way too time
- consuming). My routines had to come up with such information
- independently. My solution is store the key variables in the
- default data segment in QBASIC (its name in MASM is DGROUP). To
- save space in DGROUP, only 7 bytes of information is kept by the
- video routines. This allows transparent sharing of the
- information. The reason for such "stupid" names (B$V...) for the
- DGROUP variables is to only give the MASM routines access to such
- information, and prevent normal QBASIC routines (or someone
- else's library routines) from messing them up.
- Generally QBASIC only keeps simple variables, (INT,
- LONGINT, SINGLE and DOUBLE, and STRINGS) in DGROUP. Arrays and
- TYPE records are usually kept outside DGROUP, with only the
- STRING Descriptor or the undocumented Array descriptor kept in
- DGROUP. Thus, the library routines assume that all information
- passed from simple variables is information about a near (DGROUP)
- address. If we pass simple integers to MASM routines, and don't
- care to have MASM change those variables, we use BYVAL to send
- the information to MASM. If we want to have MASM send
- information back about multiple variables, we pass the address
- information for the variables without using BYVAL. If we usearrays, we must use a combination of BYVAL and VARSEG and VARPTR
- to get the information we need to manipulate the information
- inside the arrays. VARSEG and VARPTR are necessary because there
- is a very great chance that the arrays will be stored as far data
- (i.e. not stored in DGROUP).
- Text strings are sent by QBASIC as near address
- (relative to DS and DGROUP). The fist value in the descriptor is
- the length of the string. The second value is the offset address
- inside DGROUP. Fixed length strings are not referenced with
- string descriptors. For that reason, I don't allow such strings
- as variables in my routines.
- QBASIC requires that MASM preserve BP, SI, DI, DS, and
- keep the direction flag clear (CLD). All these routines do this.
- You will note that MICROSOFT'S CALL INTERRUPT routines do not
- save BP (apparently to give you access to some EGA VGA palette
- and character font selection routines in the BIOS), and thus will
- crash if a critical error occurs. MICROSOFT offers a replacement
- routine, that overcomes this error by preventing any change to
- BP. You should get it if you don't already have it.
- The choice of defining MASM routines as SUB's or
- FUNCTION's depends on whether you want to get information from
- MASM in DX:AX (the format for FUNCTIONs), or if the MASM routine
- either sends back no information or more than one variable (the
- format for SUBs). For simple one variable routines when MASM is
- just returning a value, use FUNCTIONs. To use such functions
- inside QBASIC you must either assign the value of the function to
- a QBASIC variable or use IF ... THEN statements (C style). For
- everything else use SUBS.
- Note due to an error in the QBASIC parser, always use
- the CALL keyword to call the library routines if there is any
- chance that you will use a colon as a separator on a line.
- Without the CALL keyword, the QBASIC parser assumes that the
- routine name followed by a colon is intended as a line label, and
- not as a SUB name. You must use CALL if you will use a SUB that
- does not need any parameters and will follow that SUB name by a
- colon.
- CGA Theory:
- The CGA is a slow, and sometimes snowy display. These
- routines deal with snow in four ways. If the CGA is good display
- (e.g. COMPAQ, AT&T, or ZENITH) then snow checking can be turned
- off automatically. If a user has a CGA display that does not
- display snow (one of many clones, none of which I have access to
- or have tested), he can use TOGGLESNOW to turn snow checking off.
- The routine can assume the that CGA is snowy and turn off the CGA
- for a instant, then turn it back on. This causes flicker, but I
- use when I am changing the entire display. See BLOADHELP. The
- last alternative is to delay writing words or bytes to the
- display until the display is in either vertical or horizontal
- retrace mode. This can be fast (1.5 times as fast as QBASIC's
- PRINT routine, while if snow checking is turned off these
- routines are 5 to six times faster than QBASIC library routines).
- Hardware interrupts are temporarily turned off, so a timer tick
- or a keystroke will not upset the counting and writing routines.
- The routines generally only allow enough time to read and writeone word. If any further manipulation is required, the wait-for-
- retrace loop has to be re-entered a second time. For speedier
- displays (MONO, HERC, EGA, VGA and MCGA), a jump is made to a
- faster routine that does not have to wait for retrace.
- There is a fifth way to avoid snow on a CGA, and that
- is send one word while the video display is in horizontal retrace
- and 400 words while in vertical retrace mode. However, that was
- considered too complicated. See, Wilton, "Programmer's Guide to
- PC & PS/2 Video Systems" (Microsoft 1987).
- Video Theory:
- Video memory in text mode starts at segment &HB000 for
- mono displays, and &HB800 for color displays. The offset of the
- first page is 0, then &H1000 (80 x 25) for as many pages as are
- allowed. The screen has no internal divisions representing ROWS
- and COLUMNS (except in HERC and CGA graphics modes), it simply is
- a logical concept. At the BIOS/hardware level, for purposes of
- displaying a character, the upper left is 0,0 and lower right of
- the display in SCREEN 0: WIDTH 80,25 is 24,79. Thus the
- location of a particular word on the display is (Row (0 biased)
- times 160 plus Column) times 2. The 160 is merely 80 columns
- times two bytes (character and attribute). That figure is
- hardcoded in my routines so I can use shifts rather than MUL's on
- old PC's and speed up the video location MACROS. On an 8088,
- shifts are faster then MUL's (some of the macros show the clocks
- for shifts versus MUL's on an 8088 and on an 80286). When
- writing to the display, the attribute is stored (and read into)
- in AH, and the character is stored (and read into) in AL. To
- only write characters or attributes, the routines increment DI
- (usually) after every write. This allows certain routines to
- write to the display sending only characters or only attributes.
- MASM Theory:
- The MASM routines were designed to be compiled with MS
- QUICK ASSEMBLER, using simplified segment names. They should
- compile with MS MASM 5.1 and above. The DOSSEG keyword might not
- be supported in MASM, so use the MASM keyword that arranges the
- segments in DOS order, rather than ALPHA order. If you use TASM
- with QUIRKS (IDEAL too?) you should be able to compile these
- programs with TASM. Because A86 does not make MS .OBJ files, you
- probably cannot use it. The same may be true with OPTASM.
- The simplified directives really save time when you
- have to identify variables on the stack, and push and pop
- variables. I use the full PROC function and the regular PROC
- keywords interchangeably. Full PROC format is not necessary when
- there is no need to address variables on the stack (i.e. no need
- to change BP to address the stack) and the QBASIC routine is
- described as a FUNCTION.
- The EVEN directive is used to word align loops for
- 80286 and 80386 machines. EVEN inserts NOPS as necessary to word
- align loops. The QBASIC BYVAL directive is used to get
- information directly from QBASIC without having to use [BX] or
- [SI] to fish out the correct information. You will note that DS
- and OFFSET are used in an unusual way in these routines. The
- string move MASM opcodes use DS:SI (source) to move video bytes
- to ES:DI (destination). We have to wait to set DS to the properaddress until we have removed information from the stack, as DS
- must point to DGROUP to properly use the stack. In addition,
- OFFSET is faster than LEA to address information in .CODE
- segment. However, for OFFSET to work, MASM must be told that
- ASSUME DS:NOTHING, ES:NOTHING. This makes the offset relative to
- beginning of code segment, and not relative to DGROUP (which is
- the default if simplified segments are used). Should anyone have
- problems with this, please let me know. To allow for
- compatibility with the 8088 chip, shifts rather than MULs are
- used for speed. I use .code to store most of my variables to
- save space in DGROUP, which is comparatively tiny and easily
- filed with string data.
- To program in OS/2 .code segment variables are
- verbotten, and you must use local variables on the stack. I
- don't have access to the OS/2 DOS compatibility box, so I don't
- know how these routines would work under OS/2. I am certain that
- none of these routines would work smoothly under protected mode.
-
- Video routine short instruction list
- ===========================================================================
- DECLARE SUB BACKFILL _
- (BYVAL ULR%, BYVAL ULC%, BYVAL LRR%, BYVAL LRC%, BYVAL ATTRIB%, BYVAL TEXTCHAR%)
- CALL BACKFILL(ULR%, ULC%, LRR%, LRC%, ATTRIB%, TEXT$)
- Description of parameters:
- Because a rectangle can be described by two points, we us the following
- data points:
- ULR Upper left row
- UCL Upper left column
- LRR Lower right row
- LRC Lower right column
- Attribute% = Background color (range 0 to 15) x 16 + Foreground color
- (Range 0 - 15). The color can be easily described in Hex as &H47
- which yields a red background and white foreground.
- TextChar% = is simply the character code that you want to fill display
- with. Common characters are 32 or space, 176 - 178 which makes for an
- attractive background character for windowing.
- Fills the display area with a character and a fixed text attribute
-
- ============================================================================
- DECLARE SUB BLOADHELP (FileName$)
- CALL BLOADHELP(FileName$)
-
- Purpose:
- to BLOAD help files without defining size of help file or type of
- display, DEFSEG location, or anything else
-
- Assumes:
- Both BSAVED file and CRT is setup for SCREEN 0, 80 x 25
- Routine does not provide any critical error support.
- Minor file errors will cause abort unless ON ERROR GOTO support
- is provided to handle common errors.
-
- FileName$ must be a near string in DGROUP, cannot be FIXED Length
- or TYPE'd.
- ===========================================================================
- DECLARE SUB CHANGEPAGE ()
- CALL CHANGEPAGE
- Purpose:
- Adjust the current VIDEOSEG to reflect current active page that is set
- by QBASIC. This routine does not change the page that is currently
- written to, you must use QBASIC to do it.
-
- Also reinitializes Video Data Area
-
- Limit:
- This will permit 25, 43, & 50 line displays
- Note on many HERC's the page size is fixed at 16kb even though
- it really is 4kb in Text Mode. Because QBASIC does not believe that
- a HERC display has video pages in text mode, this routine ignores
- ignores the possibility of video pages for HERC display.
- Typical page limits in 80 x 25 text mode:
- Mono, HERC = 0 pages
- CGA = 4 pages
- EGA (w/128kb) = 8 pages
- VGA = 8 pages
- With careful tinkering of CODE you could get 32 pages for 256kb EGA/VGA's
- and 8 pages for HERC. However, QBASIC and PRINT would become all confused.
- That is why this is left to reader to implement.
- Returns:
- Nothing, Video Data Area Filed
-
- ===========================================================================
- DECLARE SUB _
- CLEARAREA (BYVAL ULR%, BYVAL ULC%, BYVAL LRR%, BYVAL LRC%, BYVAL ATTRIB%)
- CALL CLEARAREA (ULR%, ULC%, LRR%, LRC%, ATTRIB%)
- Description of parameters:
- Because a rectangle can be described by two points, we us the following
- data points:
- ULR Upper left row
- UCL Upper left column
- LRR Lower right row
- LRC Lower right column
- Attribute% = Background color (range 0 to 15) x 16 + Foreground color
- (Range 0 - 15). The color can be easily described in Hex as &H47
- which yields a red background and white foreground.
- Changes the attribute of an area on the screen in text mode
-
- =========================================================================
- DECLARE SUB CLEARSCR (BYVAL ULR%, BYVAL ULC%, BYVAL LRR%, BYVAL LRC%,
- _BYVAL ATTRIB%)
- CALL CLEARSCR(ULR%, ULC%, LRR%, LRC%, ATTRIB%)
- range: 1-50 1-80 1-50 1-80 0-255
- Uses the video bios to scroll a window.
-
- ===========================================================================
- DECLARE SUB CLREOL ()
- CLREOL Purpose:
- Clears to end of current display line w/o changing attribute
- Assumes:
- 80 Column mode, assumes that DI has been set by SETQP; QPRINT;
- QPRINTL; or QPRNT
-
- ============================================================================
- DECLARE SUB CURSET (Mode%)
- Input:
- Mode = 0 turn off cursor
- NOTE on a VGA with ANSI.SYS installed it might not be possible
- to turn off all attributes of the cursor.
- Mode = 1 turn on normal cursor
- Mode = 2 turn on half block
- Mode = 3 turn on full block
- Returns:
- Nothing
- Purpose:
- Selects attractive cursor sizes over the default QBASIC format.
- Complicated because of need to overcome cursor emulation on VGA/EGA
- With an EGA/VGA if want a full block cursor, cannot rely on cursor
- emulation, must adjust for actual display box (assume 80 x 25).
-
- ============================================================================
- DECLARE FUNCTION DOSPRINT% (BYVAL Row%, BYVAL Col%, Text$)
- IF DOSPRINT% (Row%, Col%, Text$) THEN
- PRINT "Error in text$: null or invalid character"
- END IF
- If you don't need a return code, simply DECLARE as a SUB
-
- Print Text$ at Row%, Column
- Uses DOS Write services to print to STDERR. STDERR always == CON.
- Does not change the current background attribute, uses whatever was there.
- Only prints to page 0, but no range checks on ROW and COL. Most useful when
- operating in a multitasking environment or if want to use ANSI.SYS control
- strings.
-
- Returns:
- Error code:
- 0 if no error
- -1 if ASCII CHR$(26) found in input stream
-
- Warning:
- Assumes Text$ only contains ASCII text or Carriage return
- control characters. Any other control characters, e.g. CTRL-C
- will cause Program to terminate, probably destroying file.
- Routine checks for C/R, CTRL-C, CTRL-S, CTRL-P after each character
- If don't want this character checking, use DMPRINT
-
- Notes:
- Moves the cursor to the beginning of the string. However does not tell
- QBASIC the current cursor location. Should be a well managed function
- under WINDOWS or other multitasker.
- ============================================================================
- DECLARE FUNCTION DMPRINT% (BYVAL Row%, BYVAL Col%, Text$)
- IF DMPRINT% (Row%, Col%, Text$) THEN
- PRINT "Error in text$: null or invalid character"
- END IF
-
- If you don't need a return code, simply DECLARE as a SUB
-
- Uses DOS Write services to print to STDERR. STDERR always == CON.
- Does not change the current background attribute, uses whatever was there.
- Only prints to page 0, but no range checks on ROW and COL.
- Returns:
- Error code:
- 0 if no error
- -1 if CON error.
- If you don't need a return code, simply DECLARE as a SUB
-
- Warning:
- Ignores any control characters, merely prints string.
-
- Notes:
- Moves the cursor to the beginning of the string. However does not tell
- QBASIC the current cursor location. Should be a well managed function
- under WINDOWS or other multitasker.
-
- Routine is about 1.23 times faster than DOSPRINT on an EGA
-
- =======================================================================
- DECLARE FUNCTION DSPATTRIB% (BYVAL Foreground%, BYVAL Background%)
- Takes Background color x 16 plus Foreground color
- to make an attribute used by the system routines
- allows Background% > 15, so can blink
- This routine is not necessary, it just makes life easier for the programmer
- who remembers the format for COLOR.
-
- ============================================================================
- DECLARE FUNCTION DUALDISPLAY% ()
- Returns:
- True (<> 0) if two displays found
- False (0) if only one CRT found
-
- ============================================================================
- DECLARE EGAMONO (BYVAL Mode%)
- CALL EGAMONO (Mode%)
- Purpose:
- Forces VGA/EGA mono display to normal MONO attributes
- This allows programmer to have the same attributes appear on a
- HERC, MONO, or EGA Mono Display
- Input:
- Mode% = 0 if want default mono attributes
- Mode% <> 0 if want Herc type attributes
- Returns: Nothing
-
- Limitations: For contrast, colors can only be used against White or Intense.
- Primary colors appear as Black.
- Only White or Intense can be contrasted against Black.
- Blue and Intense Blue attributes are not underlined, unlike HERC/MONO
- All intense colors appear as white.
- Full control over VGA is not possible because of GRAY scaling and large
- number of DAC/palette registers. To get control over those two features would
- make the program much larger.
- Tinkering required for mono MCGA, but who has one of those?
-
- ============================================================================
- DECLARE SUB FADE ()
- CALL FADE
- Purpose: Clever visual effect, fades out display to white on black.
- Changes all characters to spaces.
- Works in TextMode only. Sensitive to all video modes (i.e. no snow on CGA's)
- Assumes: Display width is 80 x 25, 80 x 43 or 80 x 50
-
- ============================================================================
- DECLARE FUNCTION FINDCOLOR% ()
- Returns:
- True (<> 0) if color CRT found, even if not active
- False (0) if color CRT not found
-
- ============================================================================
- DECLARE FUNCTION FINDMONO% ()
- Returns:
- True (<> 0) if mono CRT found, even if not active
- False (0) if mono CRT not found
-
- ============================================================================
- DECLARE SUB HERCMODE (BYVAL Mode%)
- CALL HERCMODE (Mode%)
- Purpose is a to control dual displays with color and HERC
-
- Input:
- Mode = 0, Sets a Herc display to half-mode, so it can use a CGA
- Mode <> 0, Sets a Herc display to full-mode, can not use a CGA
- Does not test for existence of Herc display.
-
- =======================================================================
- DECLARE FUNCTION INCOLOR%()
- IF INCOLOR% THEN
- ... etc.
- Tests if have a color or mono display attached. Test primary display only.
- returns -1 if color display (may be a single color display)
- 0 if BW mono display
- Note will not be fooled by Herc CGA emulation routines. Doesn't test
- for single color displays like COMPAQ, AT&T
-
- =======================================================================
- DECLARE SUB LSCROLL (BYVAL Attribute%)
- CALL LSCROLL(Attribute%)
- Scrolls screen left Mostly for fun. To be really useful would have to set it up for windows
- and would have to print using VPRINT.
- Designed to handle an 80 x 25 text display
-
- ============================================================================
- DECLARE SUB MAKEBOXES _
- (BYVAL ULR%, BYVAL ULC%, BYVAL LRR%, BYVAL LRC%, BYVAL HASNO%, BYVAL BORDER%,_
- BYVAL ATTRIB%)
- CALL MAKEBOXES(ULR,ULC,LRR,LRC,HASHNO,BORDER,ATTRIB)
-
- Description of parameters:
- Because a rectangle can be described by two points, we us the following
- data points:
- ULR = Upper left row
- UCL = Upper left column
- LRR = Lower right row
- LRC = Lower right column
-
- HashNo% = is simply the character code that you want to fill display
- with. Common characters are 32 or space, 176 - 178 which makes for an
- attractive background character for windowing.
-
- Border = Select border type:
- 0 = no border
- 2 = single sided
- 3 = single vertical, double horizontal
- 4 = double vertical, single horizontal
- 5 = solid box
- Default or 1 = double vertical, double horizontal
-
- Add 256 to BORDER if want shadows. Shadow designed for 80 x 25 windows,
- to prevent page overlap. Shadow color is White on blue background for
- a mono display, is white on black background
-
- Attribute% = Background color (range 0 to 15) x 16 + Foreground color
- (Range 0 - 15). The color can be easily described in Hex as &H47
- which yields a red background and white foreground.
-
- Somewhat shorter and 1.0076 times faster than using the primitives
- in this .OBJ file to do the same thing
-
- ============================================================================
- DECLARE SUB QATTRIB (BYVAL ROW%, BYVAL COL%, BYVAL NUMCHAR%, BYVAL ATTRIB%)
- Row, Column is the starting location. attribute is the color
- and Numchar is the number of characters to change.
- Changes the attribute of characters on the screen in text mode
- Assumes: Display width is 80 columns, Rows are 25, 43, or 50
-
- ============================================================================
- QPRINT.ASM - performs Quick Printing in the QuickBASIC
- DECLARE SUB QPRINT (BYVAL ROW%, BYVAL COL%, Text$, BYVAL ATTRIBUTE%)
- Works in TextMode only, ignores all special characters
- Sensitive to all video modes (i.e. no snow on CGA's)
- If no attribute is selected, the default attribute is &H07 (normal) Assumes: Display width is 80 columns, Rows are 25, 43, or 50
-
- ===========================================================================
- DECLARE SUB QPRINTL (Text$)
- CALL QPRINTL(Text$)
- Usage: CALL SETQP(ROW%, COLL%, Attribute%) the first time to set
- the defaults to current display size. Then QPRINTL on down the display.
- You should use SETQP to start, since scroll routine needs the proper
- attribute to scroll the screen up.
-
- Purpose:
- To work similarly to PRINT Text$
-
- Major differences are:
- a) Assumes that a VIEW PRINT has been executed
- b) will not parse the Text$ and start a new line if length of
- Text$ is longer than remaining space on current line. PRINT
- is designed for formatted column printing, while this
- routine is not.
- c) if at Last Row, Column 80, QPRINTL will scroll the display
- can't stop it.
-
- Speed:
- Varies with length of Text$ and length of display
- for a color EGA on a 10 Mhz AT, the speed varies from 3% faster
- (if LEN(Text$) = 80) to 48% faster.
- Typical speed increase is 12%
-
- ============================================================================
- QPRT.ASM - performs Quick Printing in the QuickBASIC
- DECLARE SUB QPRT (BYVAL ROW%, BYVAL COL%, TEXT$)
- Works in TextMode only, ignores all special characters
- Sensitive to all video modes (i.e. no snow on CGA's)
- Does not change the attribute, uses whatever was there.
- Much faster than LOCATE X,Y : PRINT T$
- Routine is about 6 times faster than PRINT on a color EGA on an AT
- about 4.5 times faster than PRINT on a color VGA on a 386SX
- about 7 times faster than PRINT on a mono EGA on an AT
- about 1.5 to 2 times faster than PRINT on a CGA on an IBM PC
- about 5 times faster than PRINT on a HERC on an AT
- about 6 times faster than PRINT on a COMPAQ Portable
-
- Assumes: Display width is 80 columns, Max Rows are 25, 43, or 50
-
- ============================================================================
- DECLARE SUB RECOLOR (BYVAL OrigColor%, BYVAL NewColor%)
- CALL RECOLOR( OrigColor%, NewColor%)
- Purposes: Change one specific color to another without upsetting the display
- or using palette registers (which couldn't be restored easily using an EGA)
-
- Color is written as BackGround x 16 + ForeGround color
-
- Sensitive to all video modes (i.e. no snow on CGA's)
- Assumes: Display width is 80 x 25, 80 x 43 or 80 x 50
- ========================================================================
- RESTSCRN.ASM - restores 80 x 25 page text screen in QuickBASIC array
- Parameters:
- DECLARE SUB RESTSCRN (BYVAL Segment%, BYVAL Offset%)
- DIM ARRAY%(2000)
- CALL RESTSCRN(VARSEG(ARRAY%(0)), VARPTR(ARRAY%(0)))
- To save display call SAVESCRN
-
- =======================================================================
- DECLARE SUB RSCROLL (BYVAL Attribute%)
- CALL RSCROLL(Attribute%)
- Scrolls screen right
- Mostly for fun. To be really useful would have to set it up for windows
- and would have to print using VPRINT.
- Designed to handle an 80 x 25 text display
-
- ========================================================================
- SAVESCRN.ASM - saves 80 x 25 text screen page in QuickBASIC array
- Parameters:
- DECLARE SUB SAVESCRN (BYVAL Segment%, BYVAL Offset%)
- DIM ARRAY%(2000)
- CALL SAVESCRN( VARSEG(ARRAY%(0)), VARPTR(ARRAY%(0)))
- To restore call RESTSCRN
-
- ===========================================================================
- DECLARE FUNCTION S2BUFF ;put text screen in buffer
- DECLARE FUNCTION BUFF2S ;get text screen from buffer
-
- Allows movement of text screens, page 0 to and from a buffer.
- Modified to handle a CGA display so will NOT cause SNOW on a CGA
-
- Handles 80 x 25, 80 x 43, and 80 x 50 displays. Checks current status each
- time it makes a shift.
-
- Storage in Code Segment used to save space in DGROUP, makes DATA near
- without using up the limited amount of DGROUP space. However prevents
- use of program in OS/2 which prohibits any change to CodeSeg values.
-
- ===========================================================================
- DECLARE SUB SCN2BUFF () ;put text screen in buffer
- DECLARE SUB BUFF2SCN () ;get text screen from buffer
-
- Allows movement of text screens, page 0 to and from a buffer.
- Modified to handle a CGA display so will NOT cause SNOW on a CGA
-
- Handles only 80 x 25 displays. Will not crash on 80 x 43 or 80 x 50 just wont
- save the entire display. See S2BUFF if want larger displays.
-
- Storage in Code Segment used to save space in DGROUP, makes DATA near
- without using up the limited amount of DGROUP space. However prevents
- use of program in OS/2 which prohibits any change to CodeSeg values.
-
- ========================================================================= DECLARE SUB SCROLLDOWN (BYVAL ULR%, BYVAL ULC%, BYVAL LRR%, BYVAL LRC%, BYVAL
- _ ROWS%, BYVAL ATTRIB%)
- CALL SCROLLDOWN(ULR%, ULC%, LRR%, LRC%, ROWS%, ATTRIB%)
- If ROWS%=0 then entire window cleared
- Description of parameters:
- Because a rectangle can be described by two points, we us the following
- data points:
- ULR = Upper left row
- UCL = Upper left column
- LRR = Lower right row
- LRC = Lower right column
- Rows = number of rows to scroll
- Uses the video bios to scroll a window.
-
- =========================================================================
- DECLARE SUB SCROLLUP (BYVAL ULR%, BYVAL ULC%, BYVAL LRR%, BYVAL LRC%, BYVAL
- _ ROWS%, BYVAL ATTRIB%)
- CALL SCROLLUP(ULR%, ULC%, LRR%, LRC%, ROWS%, ATTRIB%)
- If ROWS%=0 then entire window cleared
- Description of parameters:
- Because a rectangle can be described by two points, we us the following
- data points:
- ULR = Upper left row
- UCL = Upper left column
- LRR = Lower right row
- LRC = Lower right column
- Rows = number of rows to scroll
- Uses the video bios to scroll a window.
-
- ===========================================================================
- DECLARE SUB SETQP (BYVAL ROW%, BYVAL COLL%, BYVAL Attribute%)
- CALL SETQP(ROW%, COLL%, Attribute%)
- Purpose:
- Initializes varibles, and sets DI to target address. This is the
- initialization routine for QPRINTL. Selects the attribute used to scroll
- the display upward.
- Assumes that user wants to set page size to full size of current dsplay
- such as 80 x 25, 80 x 43, or 80 x 50
-
- ===========================================================================
- DECLARE SUB SETBLINK (BYVAL Status%)
- CALL SETBLICK (Status%)
- Purpose:
- Toggles background blinking/intensity for MONO, CGA, EGA, VGA
- allows use of background colors that would otherwise flash
- Parameters:
- = 0 turn off blinking, enable intensity
- <> 0 to turn it on again
- Returns:
- nothing
-
- ===========================================================================
- DECLARE SUB SNOWCHECK ()
- CALL SNOWCHECK Purpose:
- Clears the snowcheck variable (B$DVIDEOPORT) if it finds a CGA
- display by OLIVETTI (AT&T), COMPAQ, or ZENITH
-
- Returns:
- Nothing DGROUP Data Area Filed
-
- ============================================================================
- DECLARE SUB SWAPCOLOR ()
- CALL SWAPCOLOR
- Purpose:
- If have a CGA and a MONO display, this makes the CGA active
- Note:
- Does not test if have either CGA or MONO installed
- See the FIND routines
- Side Effect: Display Cleared
-
- ============================================================================
- DECLARE SUB SWAPMONO ()
- CALL SWAPMONO
- Purpose:
- If have a CGA and a MONO display, this makes the MONO active
- Note:
- Does not test if have either CGA or MONO installed
- See the FIND routines
- Side Effect: Display Cleared. If have dual displays, the mono display is put
- in HERC half mode for CGA compatibility purposes. Feedback please!
-
- ===========================================================================
- DECLARE SUB TOGGLESNOW (Mode%)
- CALL TOGGLESNOW(Mode%)
- Input: If Mode% = 0, clears SNOWCHECK
- If Mode% <> 0, leaves SNOWCHECK set
- Purpose:
- Clears the snowcheck variable (B$DVIDEOPORT) if find a CGA display
- Also reinitializes Video Data Area
-
- Returns: Nothing
- Video Data Area Filed
-
- ===========================================================================
- DECLARE SUB VADDR (Row%, Column%)
- CALL VADDR(Row%, Column%)
- returns the current end of string address for the qprint routines
-
- ============================================================================
- DECLARE SUB VIDINFO (MODE%, ROW%, COLUMN%, CURPAGE%, PAGESIZE%)
- CALL VIDINFO(MODE%, ROW%, COLUMN%, CURPAGE%, PAGESIZE%)
- Purpose:
- Returns information about current video display status.
- Mode% = current video mode using BIOS format
- Row% = number of rows currently being displayed
- Cols% = width of display in columns
- Curpage% = currently active page Pagesize% = size of current page in bytes, default is 4kb
- for an 80 x 25 display.
- Note:
- PAGESIZE% on many HERC clones will be incorrect and reflect the
- information of the HERC display in HALF mode or 16kb size.
- Routine will store correct Row% length in BIOS ram for CGA, HERC & MONO
-
- ===========================================================================
- DECLARE FUNCTION VIDEOSTAT% ()
-
- VideoStatus Analyzer
- Program returns video information for use by QBASIC
- returns highest level of SCREEN mode supported by the Hardware.
- Returns information about the PRIMARY display only
- This routine with a SELECT CASE, can tell you how many display pages
- are available in text mode, SCREEN 0: WIDTH 80,25
- VGA has 8 pages (0 to 7)
- EGA with > 64kb has 8 pages (0 to 7)
- EGA with 64kb has 4 pages (0 to 3)
- CGA has 4 pages (0 to 3)
- MONO has 1 pages (0)
- HERC has 1 page in SCREEN 0 (0), 2 pages in SCREEN 3 (0 to 1)
-
- Exceptions:
- MCGA color returns a mode 11, so can contrast w/ VGA
- HERC w/o MSHERC.COM reports a -3 so you can tell user to correct matters
- COMPAQ with CGA reports -2 so can force use of monchrome attributes.
- EGA's with CGA displays report -8 if have only 64kb of memory
- EGA's with ECD display report 8 if have only 64kb of memory
-
- Returns:
- Mono = 0
- CGA = 2
- PGA = 2 (Untested, assume PGA would be treated as CGA)
- COMPAQ - CGA = -2 to tell that user may have a single color display
- HERC = 3 if have HERC and MSHERC.COM
- HERC = -3 if have HERC but w/o MSHERC.COM
- AT&T = 4, but only if have just CGA display, not EGA or VGA
- Microsoft QuickC/C makes Olivetti EGA and VGA return a separate code.
- I don't know why anyone would care if the EGA/VGA emulation were
- good.
- EGA64 = 8 Because resolution limited for 64k EGA
- EGA64 w/CGA = -8 Because resolution limited to CGA modes
- EGA = 9 Have minimum of 128kb of video ram
- EGA w/CGA = -9 Since resolution limited to CGA modes
- MCGA = 11 If have an analog color display
- MCGA = -11 If have an EGA ECD digital color display, since
- resolution of this display is limited to EGA modes
- VGA = 13
- EGA/VGA mono = 10 I guess will catch MCGA mono too
-
- The above numbering routine was selected so if the programmer put ABS in
- front of the returned value, a SCREEN command could be entered. The other
- advantage was that the routines are much faster thant the ON ERROR GOTOtraps using ERR 5 to determine what is allowed and what is not.
-
- Version 0.92
-
- Tested: CGA clone, HERC clone, EGA mono, EGA color, VGA color, COMPAQ CGA,
- VGA clone, EGA clone (Paradise clone, ATI EGA Wonder), AT&T 6300
- Not tested: PGA, VGA monochrome, MCGA (color or monochrome)
-
- ===========================================================================
- VPRINT.ASM - performs Vertical Printing in the QuickBASIC
- DECLARE SUB VPRINT (BYVAL ROW%, BYVAL COL%, Text$, BYVAL ATTRIBUTE%)
- Works in TextMode only, ignores all special characters
- Sensitive to all video modes (i.e. no snow on CGA's)
- If no attribute is selected, the default attribute is &H07 (normal)
- Assumes: Display width is 80 columns
-
- ============================================================================
- VPRT.ASM - performs Vertical Printing in the QuickBASIC
- DECLARE SUB VPRT (BYVAL ROW%, BYVAL COL%, TEXT$)
- Works in TextMode only, ignores all special characters
- Sensitive to all video modes (i.e. no snow on CGA's)
- Does not change the attribute, uses whatever was there.
- Assumes: Display width is 80 columns
-
- ==============================================================================
- WINDREST.ASM - restores a portion of the text screen in QuickBASIC;
-
- DECLARE SUB WINDREST(BYVAL ULR%,BYVAL ULC%,BYVAL LRR%,BYVAL LRC%,
- _BYVAL SEGADD%, BYVAL OFFADR% )
- CALL WINDREST(ULR%,ULC%,LRR%,LRC%,VARSEG(STORAGE(0)),VARPTR(STORAGE(0)))
- Description of parameters:
- Because a rectangle can be described by two points, we us the following
- data points:
- ULR = Upper left row
- UCL = Upper left column
- LRR = Lower right row
- LRC = Lower right column
- Dimension storage array to handle size of display in bytes
- E.g. 80 x 20 display would require an integer array of 1600
-
- ===============================================================================
- WINDSAVE.ASM - saves a portion of the text screen in QuickBASIC
- call from Quickbasic:
- DECLARE SUB WINDSAVE(BYVAL ULR%,BYVAL ULC%,BYVAL LRR%,BYVAL LRC%,
- _BYVAL SEGADD%, BYVAL OFFADR% )
- DIM STORAGE(2000)
- CALL WINDSAVE(ULR%,ULC%,LRR%,LRC%,VARSEG(STORAGE(0)),VARPTR(STORAGE(0)))
-
- Description of parameters:
- Because a rectangle can be described by two points, we us the following
- data points:
- ULR = Upper left row
- UCL = Upper left column
- LRR = Lower right row LRC = Lower right column
- Dimension storage array to handle size of display in bytes
- E.g. 80 x 20 display would require an integer array of 1600
-
- ===============================================================================
-
- Acknowledgments:
- Most of my deeper insight into video programming came from a set of
- public domain TASM video routines by Dave Bennett, (with the Toad Halls
- tweaks), from 1988. He is the source of the routine for using both the
- horizontal and vertical retrace to write to a CGA. In addition, his code
- showed the simple techniques used to write just characters and just attributes
- to the display.
-
- Author : Dave Bennett
- Version : 1.0
- Date : 11/9/88
- CIS PPN : 74635,1671
-
- Bibliography:
- General DOS/BIOS routines: Ray Duncan and Peter Norton's programming
- books. If you can only afford one book, get Duncan's. Duncan, "Advanced MS-
- DOS Programming" (2d Ed. Microsoft 1988). Very easy to read and to refer to
- specific routines. The text is very well formatted for easy reference.
- Norton, "The New Peter Norton Programmer's Guide to the IBM PC and
- PS/2" (Harper & Row 1988). A book designed to help you visualize what is
- going on. Having been "burned" by writing a book on the PC Junior, and
- experienced the agony of hardware incompatibilities in writing the Norton
- Utilities, Peter wants everybody to use the bios and documented DOS routines.
- EGA/VGA Programming:
- Michael Abrash, "Power Graphics Programming" (Que 1990). Excellent
- reprint of Programmer's Journal (Buy this magazine!) columns. Does not cover
- Super VGA and beyond (that is being done now in the Programmer's Journal).
- Mostly useful for graphics routines. The best book on the subject, and the
- only technical book that one could actually enjoy reading as a book rather
- than as a reference. See also various issues of PC Magazine for programming
- tidbits.
- Ferro, "Programmer's Guide to the EGA and VGA Cards," (Addison-Wesley
- 1988). Good, but slightly disorganized. The only book that discusses the
- registers (unfortunately more in the nature of a dictionary rather than in
- examples of how to manipulate the registers). A good list of typical bios
- defaults, which are important for the EGA since you can't read the registers.
- Herc:
- Doty, "Programmer's Guide to Hercules Graphics Cards" (Addison-Wesley
- 1988). Good book on the subject. Describes the high end Herc systems. Many
- programming examples and port descriptions.
- Herc, CGA, EGA, VGA:
- Wilton, "Programmer's Guide to PC & PS/2 Video Systems" (Microsoft
- 1987). Excellent general purpose book. Said to have some errors, though I
- have found nothing more than a few typos. Does not cover Super VGA and
- beyond. Partial information is set forth in Phoenix's "System Bios for
- PC/XT/AT Computers and Compatibles" (Addison-Wesley 1989).
- MONO and CGA:
- Bradley, "Assembly Language Programming for the IBM Personal
- Computers" (Prentice Hall 1984). Good technical descriptions of the originalPC. Only book I have seen that has really shown how to switch displays,
- manipulate DMA, make sound, and manipulate floppy disk drives at the PORT
- level (teaches you why we have BIOS and DOS routines). Good book on the 8087.
- Probably now out of print. I bought my copy at a book store that sells
- remainders.
- DOS Programming:
- Detteman, "DOS Programmer's Reference (2d Ed. Que 1989). Excellent
- book with a very helpful look at undocumented DOS. Doesn't preach about not
- using undocumented DOS as does Peter Norton.
- Waite Group "Dos Developer's Guide" (2d Ed Sams 1989). Good book on
- Expanded memory and math chips. Several good discussions of the undocumented
- DOS functions. Such a big book, that you feel you got your money's worth
- based just on weight.
- General Programming:
- Holzner, "PS/2-PC Assembly Language" (Brady 1989) Good introduction
- to assembly language programming. In many respects better than Holzner,
- "Advanced Assembly Language on the IBM PC" (Brady 1987).
- Tischer, "PC System Programming for Developers" (ABACUS 1989). Good
- technical survey of PC/AT systems. Comes with a lot of programs showing how
- to do useful things in MASM, QBASIC, PASCAL and C. The only shortcoming is
- that the book is printed on very cheap paper. One of the few books to show
- register usage of DOS and BIOS routines (important so you can save variables
- in registers rather than in memory or pushed on the stack.) Doesn't discuss
- DOS Version 4 in an integrated fashion. Such a big book, that you feel you
- got your money's worth based just on weight.
- Young, "Inside DOS: A Programmer's Guide", (Sybex 1990). Good source
- of MASM code, with a primary emphasis on C (The MASM code is similar for both
- C and QBASIC). A reprint of "MS DOS Advanced Programming" (Sybex 1988). (I
- didn't discover this until I purchased both).
- Wyatt, "Using Assembly Language" (2d Ed. QUE 1989). Some decent video
- routines. No useful description of VGA. EGA routines are primitive. Good
- insight into programming for high level languages. Complete listing of all
- the Intel keywords, but reads too much like an Intel-English disctionary.
- Most of the examples in the keyword section are not really helpful and the
- ASCII math routines are not well described. One major programming feature
- dropped from the 1st edition was the AT keyboard programming routines. Does
- this mean AT keyboards are only marginally compatible on the hardware level?
- Feedback please.
- QBASIC Programming:
- Goodwin, "QuickBASIC Advanced Programming Tools" (MIS 1989). A much
- better book for QBASIC code (sorting, popup windows, dropdown windows and
- menubar programs) than for MASM code. The MASM code relies on video bios to
- do things (which is slow, though always compatible). Moreover, screens are
- stored in STRINGs rather than arrays, which greatly limits the usefulness of
- his MASM routines. (I agree storing screens in arrays takes more work). A
- programmer can have access to several hundred KB of far data in arrays, while
- he can only have access to 30 to 40kb of precious string space in DGROUP.
- Lesser, "Advanced Quickbasic 4.0 Language Extensions with Modular
- Tools" (Bantam 1988). This is how I learned about MASM/QBASIC programming.
- Talks more about ideas that were important for QBASIC Version 3.0/MASM pre-
- version 5.1 (before simplified directives) than for QBASIC Version 4.x.
- BELIEVES in structured programming. Not too many hardware insights. Offers
- generally sound advice. Shammas, "QuickBASIC- Programming Techniques and Library Development"
- (M&T Publishing 1988). Good QBASIC code. Some of the string routines are
- fast. He has some BTREE and high level math routines.
- Books Not Recommended (How daring!):
- Murray & Pappas, "80386/80286 Assembly Language Programming"
- (Osborne/McGraw Hill 1986). Only feature of the book is a list of clock
- cycles for 80286/80386 opcodes. Reads like an Intel-English dictionary.
- Duntemann, "Assembly Language from Square One" (Scott, Foresman 1990)
- Designed for the beginning programmer. Suffers from a serious case of
- excessive cuteness. See game of "Big Bux", page 8. PC Techniques (a good
- programming magazine, like those HAX) shows he is capable of much, much more.
-
- What's next:
- Two more freeware QBASIC libraries will be released: a) Mouse and
- Keyboard routines; and b) DOS and Equipment ID routines. All will include
- MASM source and .OBJ code. If I get any significant feedback, I might even
- release revised libraries.
- I think once you are finished using these libraries you will discover
- that programming is much like fishing. At first, you just go fishing, then
- you want to catch big fish. After a while, you become content to merely catch
- fish with whatever is fast, cheap and handy.
- Oh yes, I almost forgot, in case you are wondering, I am a tax lawyer
- trying to "catch big fish"