home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Big Blue Disk 11
/
bbd11.zip
/
VIDEO7.TXT
< prev
next >
Wrap
Text File
|
1987-06-19
|
21KB
|
359 lines
|D╔══════════════════╗════════════════════════════════════════════════════════════
|D║ |5The Happy Hacker |D║════════════════════════════════════════════════════════════
|D╚══════════════════╝════════════════════════════════════════════════════════════
^C^1A VIDEO TUTORIAL -- Part 7
^Cby Joel Ellis Rea
^CBIOS Video Services
In the past two issues we discussed how to access features of the MDA and
CGA by directly manipulating both their own ports and the registers on the
Motorola 6845 CRTC chip. Such direct access is the fastest way to operate
these, or any other, video boards. However, they are not very standard, since
other systems which have similar operating systems and video display
capabilities (the PCjr, for example) may not have the same physical hardware in
the same addresses. So direct access requires specific or very compatible
hardware.
The designers of the IBM PC recognized that this might cause problems, and
also that a programmer who simply wanted to initialize an 80-column by 25 row
text display might not want to have to set a bunch of CRTC registers and video
adapter ports manually. For such video accesses, and many other things such as
low-level floppy disk control, printer access, etc., the designers provided a
special program called the Basic Input/Output Services program, or BIOS, which
resides in a special ROM chip on the motherboard of every IBM computer or
compatible. The IBM BIOS is copyrighted by IBM, but "clone" makers either
write their own or contract a company such as Phoenix to develop one for them
that is compatible with, without infringing on, the copyrighted IBM BIOS. The
measure of compatibility of a "clone's" BIOS is a major part of determining how
compatible the machine as a whole is.
First, some general information: The 8086 CPU and its sisters 8088, 80186,
80188, 80286, 80386 and 80486, all have certain registers (not to be confused
with the CRTC registers) and instructions. The instruction of most concern to
us is the "software INTerrupt request" instruction, or "INT" for short. It is
followed by a number from 00h (0) to 0FFh (255), thus allowing for 256
different interrupt requests. The registers are as follows:
┌ 8 bits ┬ 8 bits ┐ ┌─── 16 bits ───┐
╔════════╤════════╗ ╔════════════════╗
║ AH -A│X- AL ║ Accumulator ║ SP ║ Stack Pointer
╠════════╪════════╣ ╠════════════════╣
║ BH -B│X- BL ║ Base ║ BP ║ Base Pointer
╠════════╪════════╣ ╠════════════════╣
║ CH -C│X- CL ║ Count ║ SI ║ Source Index
╠════════╪════════╣ ╠════════════════╣
║ DH -D│X- DL ║ Data ║ DI ║ Destination Index
╚════════╧════════╝ ╚════════════════╝
└─── -16 bits- ───┘ ┌─── 16 bits ───┐ └─── 16 bits ───┘
╔════════════════╗
Code Segment ║ CS ║
╠════════════════╣
Data Segment ║ DS ║
╠════════════════╣
Stack Segment ║ SS ║
╠════════════════╣
Extra Segment ║ ES ║
╚════════════════╝
Note that the four 16-bit registers AX, BX, CX and DX each consist of two 8-
bit registers, xH and xL, where "x" is the first letter of the 16-bit register
name. AX consists of AH and AL, for example. The "H" means "High Byte" and
the "L" means "Low Byte". So, the full name of the register "AH" is
"Accumulator Register High Byte", while "CL" is "Count Register Low Byte", etc.
We will use the abbreviations for the remainder of this article.
The INT instruction, as I said before, simulates an interrupt to the
processor. It can also be thought of as a short subroutine call. Unlike a
true subroutine call, the program does not need to know the address of the
subroutine in memory. The INT instruction gets this information from a special
table of addresses in low memory. This means that a compatible BIOS need not
have the same routines in the same memory as IBM's BIOS. This is fortunate,
since it would be most difficult to make a compatible BIOS with the exact same
entry point addresses for all routines without violating IBM's copyright! It
also means that BIOS ROMs can be updated easily without sacrificing
compatibility.
Each INT number is assigned a specific device or service to perform. INT
10h (16 decimal) is reserved for video purposes. The registers must be loaded
prior to performing the INT 10h, according to the desired results. Register AH
is the most important, since it tells the Video BIOS routines which video
related job to perform. So to call the Video BIOS, one must load the AH
register with the number of the service to be performed, load any other
registers as needed, then do an INT 10h. Upon return, certain registers may
hold the results of the call (if any). Here is a list of the currently
implemented BIOS calls which are compatible with the MDA and CGA boards:
AH Function
── ────────
00h Set video mode
01h Set cursor type
02h Set cursor position
03h Read cursor position
04h Read light pen position
05h Select display page
06h Initialize window or scroll window contents up
07h Initialize window or scroll window contents down
08h Read attribute and character at cursor
09h Write attribute and character at cursor
0Ah Write character only at cursor
0Bh Set color palette
0Ch Write graphics pixel (plot a dot)
0Dh Read graphics pixel
0Eh Write text in "teletype mode"
0Fh Get current video mode
10h Set palette registers (PCjr and EGA only)
11h Reserved (EGA: Character generator functions)
12h Reserved (EGA: Alternate function select)
13h Write string (PC/AT and compatibles only)
There are others specifically implemented for the EGA, and others for
Hercules boards and the like. These will be discussed in a later installment.
For now, we will discuss Functions (AH) 00h through 0Fh:
Function 00h ("Set video mode") does the following: It gets the desired
mode number from the AL register, then determines which board (if multiple
boards are installed in the system) to use. It then blanks the appropriate
display temporarily by clearing the "Video" bit (bit 3) in the Control port
(03x8h) of the appropriate board (see last issue). It then looks up in a table
within the ROM BIOS for a list of the appropriate CRTC mode values (see the
issue previous to the last one) and copies these to the 6845 CRTC chip by using
the "CRTC_ Index" (03x4h) and "CRTC_Data" (03x5h) ports. It then determines
the new values for the "Control" and "Color/Palette" (color boards only) ports
and loads them in, re-enabling the video in the process by setting the "Video"
bit in the "Control" port. Finally, it clears the appro- priate area of the
video display buffer memory if the high bit was set in the AL (display mode)
register. The standard modes for CGA, MDA, PCjr (VGA) and EGA boards are as
follows:
AL Video mode Boards supported
── ───── ──── ────── ─────────
00h 40x25 text, color burst off CGA, PCjr, EGA
01h 40x25 text, color burst on CGA, PCjr, EGA
02h 80x25 text, color burst off CGA, PCjr, EGA
03h 80x25 text, color burst on CGA, PCjr, EGA
04h 320x200 4-color graphics, color burst on CGA, PCjr, EGA
05h 320x200 4-color graphics, color burst off CGA, PCjr (EGA = 04h)
06h 640x200 2-color graphics, color burst off CGA, PCjr, EGA
07h 80x25 monochrome text MDA
08h 160x200 16-color graphics PCjr (16k video RAM)
09h 320x200 16-color graphics PCjr (32k video RAM)
0Ah 640x200 4-color graphics PCjr (32k video RAM)
0Dh 320x200 16-color graphics EGA w/CGA or EGA monitor
0Eh 640x200 16-color graphics EGA w/CGA or EGA monitor
0Fh 640x350 4-attribute monochrome graphics EGA w/MDA monitor
10h 640x350 4-color graphics EGA w/EGA monitor, 64K
10h 640x350 16-color graphics EGA w/EGA monitor, 128K+
Function 01 ("Set cursor type") sets the starting and ending lines for the
blinking hardware cursor in text modes. The default values for the cursor
which are set by Function 00h (see above) are 6 and 7 for EGA, or 11 and 12 for
MDA. This is done by setting the 6845 CRTC registers "Cursor_Start" and
"Cursor_End". Register CH's low 4 bits hold the starting scan line value, and
register CL's low 4 bits hold the ending scan line value; both of which can
range from 0-15. Setting the starting value to 15 will usually make the cursor
disappear.
Function 02h ("Set cursor position") moves the cursor to a specified
position on the text display, using text rows and columns as the coordinates.
This is far easier than using the CRTC "Cursor_High" and "Cursor_Low"
registers, since those registers point to the cursor's absolute memory location
within the display buffer. The BIOS call automatically converts the specified
screen coordinates to the proper memory location, then loads the CRTC Cursor
registers appropriately. Register BH contains the video page number (usually
0). Register DH contains the text row (0-24), while DL contains the text
column (0-39 or 0-79). A more reliable way to hide the cursor than using
Function 01h (see above) is to use Function 02h to move the cursor off the
screen, say to Row 25.
Function 03h ("Read cursor position") does the reverse of Function 02h. It
reads the CRTC "Cursor_High" and "Cursor_Low" registers, takes that absolute
address and converts it to a text row and column, and loads the DH and DL
registers with those coordinates. Before the call, Register BH must be set to
the video page number (usually 0). After the call, register DH will contain
the text row (0-24) while DL will contain the text column (0-39 or 0-79).
Function 04h ("Read light pen position") will be discussed at a future time,
if enough readers express interest in how to program a light pen.
Function 05h ("Select display page") selects which page to display in a
video board/mode combination that supports multiple pages. For the CGA, it
does this by setting the CRTC "Start_High" and "Start_Low" registers to a
multiple of 2K (0800h) for 40-column text modes (8 pages, numbered 0-7), or 4K
(1000h) for 80-column text modes (4 pages, numbered 0-3). The EGA supports 8
pages in the 80-column text modes as well, and also supports up to 8 pages in
the 320x200 16-color graphics mode, up to 4 in the 640x200 16-color mode, and
up to 2 in both 640x350 modes (these limits assume 256K of on-board video RAM).
For the standard PC and PC/AT, register AL holds the desired page number. On
the PCjr, AL holds a sub-function code, and register BX either holds or returns
the desired page number(s). Note that many functions which write to the
display allow the specification of a page number. This means that the page
being displayed can be separate from the page being written to. This allows
for smooth animation or fast screen-changing effects.
Function 06h ("Initialize window or scroll window contents up") and Function
07h ("Initialize window or scroll window contents down") allow the
specification of a rectangular text area, or "window", which can then be
cleared or scrolled independently of the rest of the screen. By setting the
window to cover the full screen, the entire screen is either scrolled or
cleared. This is how normal screen-clearing and text-scrolling operations are
performed. Register AL contains the number of lines to scroll, or 0 to clear
the window. Register BH contains the attribute to be used for the area left
blank by the scroll or clear. Registers CX and DX contain the bounds of the
window as follows:
Register Range(s) Meaning
──────── ──────── ───────
CH (0-24) Top text row, or upper left corner's Y.
CL (0-39/79) Left text column, or upper left corner's X.
DH (CH-24) Bottom text row, or lower right corner's Y.
DL (DL-39/79) Right text column, or lower right corner's X.
Of course, these two functions are identical except for the fact that
Function 06h scrolls up and Function 07h scrolls down. Either can be used to
clear the window or screen. Note that only the currently-active display page
is affected (see Function 05h above).
Both functions use some RAM locations to reset the Control and Palette ports
to legitimate values. This causes any changes made to them to "vanish" after a
BIOS scroll or screen clear. Next issue we will discuss a way to get around
this.
Function 08h ("Read attribute and character at cursor") loads Register AX
with the attribute byte (in AH) and the ASCII character code (in AL) at the
current cursor position in the text page specified by Register BH.
Function 09h ("Write attribute and character at cursor") places a desired
character (ASCII code in AL) with a specified attribute byte or color code (in
BL) at the current cursor location in the specified video page (in BH). It
does this CX times, thus a row of a certain character can be "drawn" with a
single call. The cursor is NOT moved by this call, and no characters are
considered "special" in any way -- not even return, line feed, backspace or
bell. In graphics mode, the characters are "drawn" by plotting 8 pixels at a
time; and if the high bit (bit 7) of the attribute byte (in BL) is set, the
characters will be drawn in XOR mode, which means that they can overwrite a
complex graphics background, then simply re-plotting the text will seem to
erase them, restoring the previous contents of the graphics under the "text";
and the bit patterns for characters whose ASCII codes are greater than 7Fh
(127) can be programmed.
Function 0Ah ("Write character only at cursor") is identical to Function 09h
(see above) except that the attribute at that character position remains the
way it was. In graphics mode, the BL register's high bit can still be used to
specify XOR mode. Other than that, regiester BL's contents are ignored
Function 0Bh ("Set color palette") on the CGA sets the "CGA_Palette"
register as follows: If BH=0, BL contains the 4 bits to load into the low
nybble of the Palette register, thus setting the border color in text modes,
the background color in 320x200 graphics modes, and the foreground color in the
640x200 graphics mode. If BH=1, BL contains either a 0 or a 1, which is loaded
into the "CGA_P_Palette" bit of the "CGA_Palette" register, thus changing the
current 320x200 color graphics palette. BL=0 selects the Green-Red-Yellow
palette, while BL=1 selects the Cyan-Magenta-White palette. For the PCjr, this
function can be used to select individual palette colors.
Function 0Ch ("Write graphics pixel") plots a point on the graphics screen.
For CGA, location AL must be loaded with the value of the color to plot the dot
with (0-3 in 320x200 4-color modes, 0-1 in 640x200 2-color mode) -- the high
bit can be set to do the plot in XOR mode. Register CX contains the
horizontal, or X-coordinate of the pixel (0-319 in 320-wide modes, 0-639 in
640-wide modes); while Register DX contains the vertical, or Y-coordinate of
the pixel (0-199 in 200-line modes, 0-349 in 350-line EGA modes).
Function 0Dh ("Read graphics pixel") is used to determine the color of a
specified pixel in the graphics modes. The coordinates must be loaded into
registers CX and DX the same as in Function 0Ch (see above). After the call,
register AL holds the pixel value, or color.
Function 0Eh ("Write text in 'teletype' mode") is similar to Function 0Ah
("Write character only at cursor" -- see above), except that the cursor IS
moved to the next position, unless the character is a linefeed (cursor is moved
down one line), carriage return (cursor is moved to the first position on the
line), backspace (cursor is moved backwards one position), or bell (cursor is
not moved, but the speaker sounds a tone). Automatic line-wrapping and screen-
scrolling are also provided by this function. If the screen is scrolled, this
function automatically calls Function 06h ("Initialize window or scroll window
contents up") to scroll the screen, passing as the "fill" attribute the
attribute of the last character to be written before the scroll. There is no
way to specify the attribute of a text character with this function. If you
wish to set attributes, you should write each attribute with Function 09H
("Write attribute and character at cursor" -- see above) with a space character
(20h, 32), followed by this Function to write the character with proper cursor
movements. This is the BIOS call that MS-DOS uses for its console driver (CON)
output. As in Functions 09h and 0Ah, register BH holds the desired text page,
and register BL holds the color to use in graphics mode text plotting. The
repeat factor (CX) is not used here.
Function 0Fh ("Get current display mode") gets the currently active display
mode (set with Function 00h -- see above) and the current display page (set
with Function 05h -- see above). No registers (except for AH containing the
Function code 0Fh, of course) need be set prior to the call. Upon return, AL
contains the current mode (as per Function 00h) and BH contains the active
display page.
Performing INT calls from BASICA or GW-BASIC can be difficult. It basically
requires a machine-language routine to be made available. Turbo Pascal, on the
other hand, provides a nice programmer's interface to the INT function. One
simply defines a RECORD VARiable to hold the registers, then call the "Intr"
PROCEDURE with the desired INT code and registers variable. These lines will
define the TYPE and VARiable that the "Intr" (and "MsDos") PROCEDUREs expect:
^1TYPE
^1 ...
^1 iAPX = RECORD CASE Boolean OF
^1 False: (AX, BX, CX, DX, BP, SI, DI, DS, ES, Flags): Integer;
^1 True: (AL, AH, BL, BH, CL, CH, DL, DH): Byte
^1 END; { RECORD iAPX }
^1 ...
^1VAR
^1 ...
^1 registers: iAPX
^1 ...
As an example, to scroll a window on the 80x25 text screen consisting of
rows 5-20 and columns 10-70 4 lines downward, filling the new blank lines with
a dark red background with a light yellow (but invisible, since there is no
text) foreground, you could do this:
^1PROCEDURE scroll4down;
^1 BEGIN { PROCEDURE scroll4down }
^1 WITH registers DO BEGIN
^1 CH := 5; { Top row of window }
^1 DH := 20; { Bottom row of window }
^1 CL := 10; { Left column of window }
^1 DL := 70; { Right column of window }
^1 BH := (Red SHR 4) OR Yellow; { Fill attribute = $4E }
^1 AL := 4; { Lines to scroll }
^1 AH := $7 { "Initialize window or scroll window contents down" }
^1 END; { WITH registers }
^1 Intr ($10, registers) { BIOS call, $10 = Video services }
^1 END; { PROCEDURE scroll4down }
On this issue of Big Blue Disk is a demo program which demonstrates the
various BIOS calls discussed here. Simply press the [─┘] key to run it from
here, or you can press [Esc] to get back to the menu, re-select this article,
and choose "Run it" from the menu.
Next issue we will discuss how the BIOS keeps track of certain information,
and how one can obtain very interesting effects by "tricking" the ROM BIOS.
Two effects in particular will be to enable bright background by sacrificing
the blink capability, but enable that effect to survive a Function 06h or 07h
scroll or screen clear; and to trick BIOS into thinking you've switched
graphics modes when you haven't, thus allowing both 40-column and 80-column
text on the screen at the same time in 640x200 graphics mode.