home *** CD-ROM | disk | FTP | other *** search
/ For Beginners & Professional Hackers / cd.iso / docum / advdos.doc / s1c06 < prev    next >
Encoding:
Text File  |  1992-04-21  |  41.4 KB  |  853 lines

  1. ────────────────────────────────────────────────────────────────────────────
  2. Chapter 6  Video Display
  3.  
  4.   The visual presentation of an application program is one of its most
  5.   important elements. Users frequently base their conclusions about a
  6.   program's performance and "polish" on the speed and attractiveness of its
  7.   displays. Therefore, a feel for the computer system's display facilities
  8.   and capabilities at all levels, from MS-DOS down to the bare hardware, is
  9.   important to you as a programmer.
  10.  
  11.  
  12. Video Display Adapters
  13.  
  14.   The video display adapters found in IBM PC─compatible computers have a
  15.   hybrid interface to the central processor. The overall display
  16.   characteristics, such as vertical and horizontal resolution, background
  17.   color, and palette, are controlled by values written to I/O ports whose
  18.   addresses are hardwired on the adapter, whereas the appearance of each
  19.   individual character or graphics pixel on the display is controlled by a
  20.   specific location within an area of memory called the regen buffer or
  21.   refresh buffer. Both the CPU and the video controller access this memory;
  22.   the software updates the display by simply writing character codes or bit
  23.   patterns directly into the regen buffer. (This is called memory-mapped
  24.   I/O.)
  25.  
  26.   The following adapters are in common use as this book is being written:
  27.  
  28.   ■  Monochrome/Printer Display Adapter (MDA). Introduced with the original
  29.      IBM PC in 1981, this adapter supports 80-by-25 text display on a green
  30.      (monochrome) screen and has no graphics capabilities at all.
  31.  
  32.   ■  Color/Graphics Adapter (CGA). Also introduced by IBM in 1981, this
  33.      adapter supports 40-by-25 and 80-by-25 text modes and 320-by-200,
  34.      4-color or 640-by-200, 2-color graphics (all-points-addressable, or
  35.      APA) modes on composite or digital RGB monitors.
  36.  
  37.   ■  Enhanced Graphics Adapter (EGA). Introduced by IBM in 1985 and upwardly
  38.      compatible from the CGA, this adapter adds support for 640-by-350,
  39.      16-color graphics modes on digital RGB monitors. It also supports an
  40.      MDA-compatible text mode.
  41.  
  42.   ■  Multi-Color Graphics Array (MCGA). Introduced by IBM in 1987 with the
  43.      Personal System/2 (PS/2) models 25 and 30, this adapter is partially
  44.      compatible with the CGA and EGA and supports 640-by-480, 2-color or
  45.      320-by-200, 256-color graphics on analog RGB monitors.
  46.  
  47.   ■  Video Graphics Array (VGA). Introduced by IBM in 1987 with the PS/2
  48.      models 50, 60, and 80, this adapter is upwardly compatible from the EGA
  49.      and supports 640-by-480, 16-color or 320-by-200, 256-color graphics on
  50.      analog RGB monitors. It also supports an MDA-compatible text mode.
  51.  
  52.   ■  Hercules Graphics Card, Graphics CardPlus, and InColor Cards. These are
  53.      upwardly compatible from the MDA for text display but offer graphics
  54.      capabilities that are incompatible with all of the IBM adapters.
  55.  
  56.   The locations of the regen buffers for the various IBM PC─compatible
  57.   adapters are shown in Figure 6-1.
  58.  
  59.          ┌───────────────────────────────────────────────────────┐
  60.          │                       ROM BIOS                        │
  61.   FE000H ├───────────────────────────────────────────────────────┤
  62.          │          System ROM, Stand-alone BASIC, etc.          │
  63.   F4000H ├───────────────────────────────────────────────────────┤
  64.          │             Reserved for BIOS extensions              │
  65.          │             (hard-disk controller, etc.)              │
  66.   C0000H ├───────────────────────────────────────────────────────┤
  67.          │                       Reserved                        │
  68.   BC000H ├───────────────────────────────────────────────────────┤
  69.          │    16 KB regen buffer for CGA, EGA, MCGA, and VGA     │
  70.          │       in text modes and 200-line graphics modes       │
  71.   B8000H ├───────────────────────────────────────────────────────┤
  72.          │                       Reserved                        │
  73.   B1000H ├───────────────────────────────────────────────────────┤
  74.          │         4 KB Monochrome Adapter regen buffer          │
  75.   B0000H ├───────────────────────────────────────────────────────┤
  76.          │       Regen buffer area for EGA, MCGA, and VGA        │
  77.          │        in 350-line or 480-line graphics modes         │
  78.   A0000H ├───────────────────────────────────────────────────────┤
  79.          │             Transient part of COMMAND.COM             │
  80.          ├───────────────────────────────────────────────────────┤
  81.          │                Transient program area                 │
  82.   varies ├───────────────────────────────────────────────────────┤
  83.          │                MS-DOS and its buffers,                │
  84.          │              tables, and device drivers               │
  85.   00400H ├───────────────────────────────────────────────────────┤
  86.          │                   Interrupt vectors                   │
  87.   00000H └───────────────────────────────────────────────────────┘
  88.  
  89.   Figure 6-1.  Memory diagram of an IBM PC─compatible personal computer,
  90.   showing the locations of the regen buffers for various adapters.
  91.  
  92.  
  93. Support Considerations
  94.  
  95.   MS-DOS offers several functions to transfer text to the display. Version 1
  96.   supported only Teletype-like output capabilities; version 2 added an
  97.   optional ANSI console driver to allow the programmer to clear the screen,
  98.   position the cursor, and select colors and attributes with standard escape
  99.   sequences embedded in the output. Programs that use only the MS-DOS
  100.   functions will operate properly on any computer system that runs MS-DOS,
  101.   regardless of the level of IBM hardware compatibility.
  102.  
  103.   On IBM PC─compatible machines, the ROM BIOS contains a video driver that
  104.   programs can invoke directly, bypassing MS-DOS. The ROM BIOS functions
  105.   allow a program to write text or individual pixels to the screen or to
  106.   select display modes, video pages, palette, and foreground and background
  107.   colors. These functions are relatively efficient (compared with the MS-DOS
  108.   functions, at least), although the graphics support is primitive.
  109.  
  110.   Unfortunately, the display functions of both MS-DOS and the ROM BIOS were
  111.   designed around the model of a cursor-addressable terminal and therefore
  112.   do not fully exploit the capabilities of the memory-mapped, high-bandwidth
  113.   display adapters used on IBM PC─compatible machines. As a result, nearly
  114.   every popular interactive application with full-screen displays or
  115.   graphics capability ignores both MS-DOS and the ROM BIOS and writes
  116.   directly to the video controller's registers and regen buffer.
  117.  
  118.   Programs that control the hardware directly are sometimes called
  119.   "ill-behaved," because they are performing operations that are normally
  120.   reserved for operating-system device drivers. These programs are a severe
  121.   management problem in multitasking real-mode environments such as DesqView
  122.   and Microsoft Windows, and they are the main reason why such environments
  123.   are not used more widely. It could be argued, however, that the blame for
  124.   such problematic behavior lies not with the application programs but with
  125.   the failure of MS-DOS and the ROM BIOS──even six years after the first
  126.   appearance of the IBM PC──to provide display functions of adequate range
  127.   and power.
  128.  
  129.  
  130. MS-DOS Display Functions
  131.  
  132.   Under MS-DOS versions 2.0 and later, the preferred method for sending text
  133.   to the display is to use handle-based Int 21H Function 40H (Write File or
  134.   Device). When an application program receives control, MS-DOS has already
  135.   assigned it handles for the standard output (1) and standard error (2)
  136.   devices, and these handles can be used immediately. For example, the
  137.   sequence at the top of the following page writes the message hello to the
  138.   display using the standard output handle.
  139.  
  140.   ──────────────────────────────────────────────────────────────────────────
  141.   msg     db      'hello'     ; message to display
  142.   msg_len equ     $-msg       ; length of message
  143.           .
  144.           .
  145.           .
  146.           mov     ah,40h      ; function 40h = write file or device
  147.           mov     bx,1        ; BX = standard output handle
  148.           mov     cx,msg_len  ; CX = message length
  149.           mov     dx,seg msg  ; DS:DX = address of message
  150.           mov     ds,dx
  151.           mov     dx,offset msg
  152.           int     21h         ; transfer to MS-DOS
  153.           jc      error       ; jump if error detected
  154.           .
  155.           .
  156.           .
  157.   ──────────────────────────────────────────────────────────────────────────
  158.  
  159.   If there is no error, the function returns the carry flag cleared and the
  160.   number of characters actually transferred in register AX. Unless a Ctrl-Z
  161.   is embedded in the text or the standard output is redirected to a disk
  162.   file and the disk is full, this number should equal the number of
  163.   characters requested.
  164.  
  165.   As in the case of keyboard input, the user's ability to specify
  166.   command-line redirection parameters that are invisible to the application
  167.   means that if you use the predefined standard output handle, you can't
  168.   always be sure where your output is going. However, to ensure that your
  169.   output actually goes to the display, you can use the predefined standard
  170.   error handle, which is always opened to the CON (logical console) device
  171.   and is not redirectable.
  172.  
  173.   As an alternative to the standard output and standard error handles, you
  174.   can bypass any output redirection and open a separate channel to CON,
  175.   using the handle obtained from that open operation for character output.
  176.   For example, the following code opens the console display for output and
  177.   then writes the string hello to it:
  178.  
  179.   ──────────────────────────────────────────────────────────────────────────
  180.   fname   db      'CON',0      ; name of CON device
  181.   handle  dw      0            ; handle for CON device
  182.   msg     db      'hello'      ; message to display
  183.   msg_len equ     $-msg        ; length of message
  184.           .
  185.           .
  186.           .
  187.           mov     ax,3d02h     ; AH = function 3dh = open
  188.                                ; AL = mode = read/write
  189.           mov     dx,seg fname ; DS:DX = device name
  190.           mov     ds,dx
  191.           mov     dx,offset fname
  192.           int     21h          ; transfer to MS-DOS
  193.           jc      error        ; jump if open failed
  194.           mov     handle,ax    ; save handle for CON
  195.           .
  196.           .
  197.           .
  198.           mov     ah,40h       ; function 40h = write
  199.           mov     cx,msg_len   ; CX = message length
  200.           mov     dx,seg msg   ; DS:DX = address of message
  201.           mov     ds,dx
  202.           mov     dx,offset msg
  203.           mov     bx,handle    ; BX = CON device handle
  204.           int     21h          ; transfer to MS-DOS
  205.           jc      error        ; jump if error detected
  206.           .
  207.           .
  208.           .
  209.   ──────────────────────────────────────────────────────────────────────────
  210.  
  211.   As with the keyboard input functions, MS-DOS also supports traditional
  212.   display functions that are upwardly compatible from the corresponding CP/M
  213.   output calls:
  214.  
  215.   ■  Int 21H Function 02H sends the character in the DL register to the
  216.      standard output device. It is sensitive to Ctrl-C interrupts, and it
  217.      handles carriage returns, linefeeds, bell codes, and backspaces
  218.      appropriately.
  219.  
  220.   ■  Int 21H Function 06H transfers the character in the DL register to the
  221.      standard output device, but it is not sensitive to Ctrl-C interrupts.
  222.      You must take care when using this function, because it can also be
  223.      used for input and for status requests.
  224.  
  225.   ■  Int 21H Function 09H sends a string to the standard output device. The
  226.      string is terminated by the $ character.
  227.  
  228.   With MS-DOS version 2 or later, these three traditional functions are
  229.   converted internally to handle-based writes to the standard output and
  230.   thus are susceptible to output redirection.
  231.  
  232.   The sequence at the top of the following page sounds a warning beep by
  233.   sending an ASCII bell code (07H) to the display driver using the
  234.   traditional character-output call Int 21H Function 02H.
  235.  
  236.   ──────────────────────────────────────────────────────────────────────────
  237.           .
  238.           .
  239.           .
  240.           mov     dl,7        ; 07h = ASCII bell code
  241.           mov     ah,2        ; function 02h = display character
  242.           int     21h         ; transfer to MS-DOS
  243.           .
  244.           .
  245.           .
  246.   ──────────────────────────────────────────────────────────────────────────
  247.  
  248.   The following sequence uses the traditional string-output call Int 21H
  249.   Function 09H to display a string:
  250.  
  251.   ──────────────────────────────────────────────────────────────────────────
  252.   msg     db      'hello$'
  253.           .
  254.           .
  255.           .
  256.           mov     dx,seg msg  ; DS:DX = message address
  257.           mov     ds,dx
  258.           mov     dx,offset msg
  259.           mov     ah,9        ; function 09h = write string
  260.           int     21h         ; transfer to MS-DOS
  261.           .
  262.           .
  263.           .
  264.   ──────────────────────────────────────────────────────────────────────────
  265.  
  266.   Note that MS-DOS detects the $ character as a terminator and does not
  267.   display it on the screen.
  268.  
  269. Screen Control with MS-DOS Functions
  270.  
  271.   With version 2.0 or later, if MS-DOS loads the optional device driver
  272.   ANSI.SYS in response to a DEVICE directive in the CONFIG.SYS file,
  273.   programs can clear the screen, control the cursor position, and select
  274.   foreground and background colors by embedding escape sequences in the text
  275.   output. Escape sequences are so called because they begin with an escape
  276.   character (1BH), which alerts the driver to intercept and interpret the
  277.   subsequent characters in the sequence. When the ANSI driver is not loaded,
  278.   MS-DOS simply passes the escape sequence to the display like any other
  279.   text, usually resulting in a chaotic screen.
  280.  
  281.   The escape sequences that can be used with the ANSI driver for screen
  282.   control are a subset of those defined in the ANSI 3.64─1979 Standard.
  283.   These standard sequences are summarized in Figure 6-2. Note that case is
  284.   significant for the last character in an escape sequence and that numbers
  285.   must always be represented as ASCII digit strings, not as their binary
  286.   values. (A separate set of escape sequences supported by ANSI.SYS, but not
  287.   compatible with the ANSI standard, may be used for reprogramming and
  288.   remapping the keyboard.)
  289.  
  290.  
  291.   Escape sequence    Meaning
  292.   ──────────────────────────────────────────────────────────────────────────
  293.   Esc[2J             Clear screen; place cursor in upper left corner (home
  294.                      position).
  295.   Esc[K              Clear from cursor to end of line.
  296.   Esc[row;colH       Position cursor. (Row is the y coordinate in the range
  297.                      1─25 and col is the x coordinate in the range 1─80 for
  298.                      80-by-25 text display modes.) Escape sequences
  299.                      terminated with the letter f instead of H have the same
  300.                      effect.
  301.   Esc[nA             Move cursor up n rows.
  302.   Esc[nB             Move cursor down n rows.
  303.   Esc[nC             Move cursor right n columns.
  304.   Esc[nD             Move cursor left n columns.
  305.   Esc[s              Save current cursor position.
  306.   Esc[u              Restore cursor to saved position.
  307.   Esc[6n             Return current cursor position on the standard input
  308.                      handle in the format Esc[row;colR.
  309.   Esc[nm             Select character attributes:
  310.                       0 = no special attributes
  311.                       1 = high intensity
  312.                       2 = low intensity
  313.                       3 = italic
  314.                       4 = underline
  315.                       5 = blink
  316.                       6 = rapid blink
  317.                       7 = reverse video
  318.                       8 = concealed text (no display)
  319.                      30 = foreground black
  320.                      31 = foreground red
  321.                      32 = foreground green
  322.                      33 = foreground yellow
  323.                      34 = foreground blue
  324.                      35 = foreground magenta
  325.                      36 = foreground cyan
  326.                      37 = foreground white
  327.                      40 = background black
  328.                      41 = background red
  329.                      42 = background green
  330.                      43 = background yellow
  331.                      44 = background blue
  332.                      45 = background magenta
  333.                      46 = background cyan
  334.                      47 = background white
  335.   Esc[=nh            Select display mode:
  336.                       0 = 40-by-25, 16-color text (color burst off)
  337.                       1 = 40-by-25, 16-color text
  338.                       2 = 80-by-25, 16-color text (color burst off)
  339.                       3 = 80-by-25, 16-color text
  340.                       4 = 320-by-200, 4-color graphics
  341.                       5 = 320-by-200, 4-color graphics (color burst off)
  342.                       6 = 620-by-200, 2-color graphics
  343.                      14 = 640-by-200, 16-color graphics (EGA and VGA,
  344.                      MS-DOS 4.0)
  345.                      15 = 640-by-350, 2-color graphics (EGA and VGA,
  346.                      MS-DOS 4.0)
  347.                      16 = 640-by-350, 16-color graphics (EGA and VGA,
  348.                      MS-DOS 4.0)
  349.                      17 = 640-by-480, 2-color graphics (MCGA and VGA,
  350.                      MS-DOS 4.0)
  351.                      18 = 640-by-480, 16-color graphics (VGA, MS-DOS 4.0)
  352.                      19 = 320-by-200, 256-color graphics (MCGA and VGA,
  353.                      MS-DOS 4.0)
  354.                      Escape sequences terminated with l instead of h have
  355.                      the same effect.
  356.   Esc[=7h            Enable line wrap.
  357.   Esc[=7l            Disable line wrap.
  358.   ──────────────────────────────────────────────────────────────────────────
  359.  
  360.  
  361.   Figure 6-2.  The ANSI escape sequences supported by the MS-DOS ANSI.SYS
  362.   driver. Programs running under MS-DOS 2.0 or later may use these
  363.   functions, if ANSI.SYS is loaded, to control the appearance of the display
  364.   in a hardware-independent manner. The symbol Esc indicates an ASCII escape
  365.   code──a character with the value 1BH. Note that cursor positions in ANSI
  366.   escape sequences are one-based, unlike the cursor coordinates used by the
  367.   IBM ROM BIOS, which are zero-based. Numbers embedded in an escape sequence
  368.   must always be represented as a string of ASCII digits, not as their
  369.   binary values.
  370.  
  371. Binary Output Mode
  372.  
  373.   Under MS-DOS version 2 or later, you can substantially increase display
  374.   speeds for well-behaved application programs without sacrificing hardware
  375.   independence by selecting binary (raw) mode for the standard output. In
  376.   binary mode, MS-DOS does not check between each character it transfers to
  377.   the output device for a Ctrl-C waiting at the keyboard, nor does it filter
  378.   the output string for certain characters such as Ctrl-Z.
  379.  
  380.   Bit 5 in the device information word associated with a device handle
  381.   controls binary mode. Programs access the device information word by using
  382.   Subfunctions 00H and 01H of the MS-DOS IOCTL function (I/O Control, Int
  383.   21H Function 44H). For example, the sequence on the following page places
  384.   the standard output handle into binary mode.
  385.  
  386.   ──────────────────────────────────────────────────────────────────────────
  387.                               ; get device information...
  388.           mov     bx,1        ; standard output handle
  389.           mov     ax,4400h    ; function 44h subfunction 00h
  390.           int     21h         ; transfer to MS-DOS
  391.  
  392.           mov     dh,0        ; set upper byte of DX = 0
  393.           or      dl,20h      ; set binary mode bit in DL
  394.  
  395.                               ; write device information...
  396.                               ; (BX still has handle)
  397.           mov     ax,4401h    ; function 44h subfunction 01h
  398.           int     21h         ; transfer to MS-DOS
  399.   ──────────────────────────────────────────────────────────────────────────
  400.  
  401.   Note that if a program changes the mode of any of the standard handles, it
  402.   should restore those handles to ASCII (cooked) mode before it exits.
  403.   Otherwise, subsequent application programs may behave in unexpected ways.
  404.   For more detailed information on the IOCTL function, see Section II of
  405.   this book, "MS-DOS Functions Reference."
  406.  
  407.  
  408. The ROM BIOS Display Functions
  409.  
  410.   You can somewhat improve the display performance of programs that are
  411.   intended for use only on IBM PC─compatible machines by using the ROM BIOS
  412.   video driver instead of the MS-DOS output functions. Accessed by means of
  413.   Int 10H, the ROM BIOS driver supports the following functions for all of
  414.   the currently available IBM display adapters:
  415.  
  416.  
  417.   Function           Action
  418.   ──────────────────────────────────────────────────────────────────────────
  419.   Display mode control
  420.   00H               Set display mode.
  421.   0FH               Get display mode.
  422.  
  423.   Cursor control
  424.   01H               Set cursor size.
  425.   02H               Set cursor position.
  426.   03H               Get cursor position and size.
  427.  
  428.   Writing to the display
  429.   09H               Write character and attribute at cursor.
  430.   0AH               Write character-only at cursor.
  431.   0EH               Write character in teletype mode.
  432.  
  433.   Reading from the display
  434.   08H               Read character and attribute at cursor.
  435.  
  436.   Graphics support
  437.   0CH               Write pixel.
  438.   0DH               Read pixel.
  439.  
  440.   Scroll or clear display
  441.   06H               Scroll up or initialize window.
  442.   07H               Scroll down or initialize window.
  443.  
  444.   Miscellaneous
  445.   04H               Read light pen.
  446.   05H               Select display page.
  447.   0BH               Select palette/set border color.
  448.   ──────────────────────────────────────────────────────────────────────────
  449.  
  450.  
  451.   Additional ROM BIOS functions are available on the EGA, MCGA, VGA, and
  452.   PCjr to support the enhanced features of these adapters, such as
  453.   programmable palettes and character sets (fonts). Some of the functions
  454.   are valid only in certain display modes.
  455.  
  456.   Each display mode is characterized by the number of colors it can display,
  457.   its vertical resolution, its horizontal resolution, and whether it
  458.   supports text or graphics memory mapping. The ROM BIOS identifies it with
  459.   a unique number. Section III of this book, "IBM ROM BIOS and Mouse
  460.   Functions Reference," documents all of the ROM BIOS Int 10H functions and
  461.   display modes.
  462.  
  463.   As you can see from the preceding list, the ROM BIOS offers several
  464.   desirable capabilities that are not available from MS-DOS, including
  465.   initialization or scrolling of selected screen windows, modification of
  466.   the cursor shape, and reading back the character being displayed at an
  467.   arbitrary screen location. These functions can be used to isolate your
  468.   program from the hardware on any IBM PC─compatible adapter. However, the
  469.   ROM BIOS functions do not suffice for the needs of a high-performance,
  470.   interactive, full-screen program such as a word processor. They do not
  471.   support the rapid display of character strings at an arbitrary screen
  472.   position, and they do not implement graphics operations at the level
  473.   normally required by applications (for example, bit-block transfers and
  474.   rapid drawing of lines, circles, and filled polygons). And, of course,
  475.   they are of no use whatsoever in non-IBM display modes such as the
  476.   monochrome graphics mode of the Hercules Graphics Card.
  477.  
  478.   Let's look at a simple example of a call to the ROM BIOS video driver. The
  479.   following sequence writes the string hello to the screen:
  480.  
  481.   ──────────────────────────────────────────────────────────────────────────
  482.   msg     db      'hello'
  483.   msg_len equ     $-msg
  484.           .
  485.           .
  486.           .
  487.           mov     si,seg msg  ; DS:SI = message address
  488.           mov     ds,si
  489.           mov     si,offset msg
  490.           mov     cx,msg_len  ; CX = message length
  491.           cld
  492.   next:   lodsb               ; get AL = next character
  493.           push    si          ; save message pointer
  494.           mov     ah,0eh      ; int 10h function 0eh = write
  495.                               ; character in teletype mode
  496.           mov     bh,0        ; assume video page 0
  497.           mov     bl,color    ; (use in graphics modes only)
  498.           int     10h         ; transfer to ROM BIOS
  499.           pop     si          ; restore message pointer
  500.           loop    next        ; loop until message done
  501.           .
  502.           .
  503.           .
  504.   ──────────────────────────────────────────────────────────────────────────
  505.  
  506.   (Note that the SI and DI registers are not necessarily preserved across a
  507.   call to a ROM BIOS video function.)
  508.  
  509.  
  510. Memory-mapped Display Techniques
  511.  
  512.   Display performance is best when an application program takes over
  513.   complete control of the video adapter and the refresh buffer. Because the
  514.   display is memory-mapped, the speed at which characters can be put on the
  515.   screen is limited only by the CPU's ability to copy bytes from one
  516.   location in memory to another. The trade-off for this performance is that
  517.   such programs are highly sensitive to hardware compatibility and do not
  518.   always function properly on "clones" or even on new models of IBM video
  519.   adapters.
  520.  
  521. Text Mode
  522.  
  523.   Direct programming of the IBM PC─compatible video adapters in their text
  524.   display modes (sometimes also called alphanumeric display modes) is
  525.   straightforward. The character set is the same for all, and the cursor
  526.   home position──(x,y) = (0,0)──is defined to be the upper left corner of
  527.   the screen (Figure 6-3). The MDA uses 4 KB of memory starting at segment
  528.   B000H as a regen buffer, and the various adapters with both text and
  529.   graphics capabilities (CGA, EGA, MCGA, and VGA) use 16 KB of memory
  530.   starting at segment B800H. (See Figure 6-1.) In the latter case, the 16
  531.   KB is divided into "pages" that can be independently updated and
  532.   displayed.
  533.  
  534.    (0,0)┌─────────────────────────────────┐(79,0)
  535.         │                                 │
  536.         │                                 │
  537.         │                                 │
  538.         │                                 │
  539.         │                                 │
  540.         │                                 │
  541.         │                                 │
  542.   (0,24)└─────────────────────────────────┘(79,24)
  543.  
  544.   Figure 6-3.  Cursor addressing for 80-by-25 text display modes (IBM ROM
  545.   BIOS modes 2, 3, and 7).
  546.  
  547.   Each character-display position is allotted 2 bytes in the regen buffer.
  548.   The first byte (even address) contains the ASCII code of the character,
  549.   which is translated by a special hardware character generator into a
  550.   dot-matrix pattern for the screen. The second byte (odd address) is the
  551.   attribute byte. Several bit fields in this byte control such features as
  552.   blinking, intensity (highlighting), and reverse video, depending on the
  553.   adapter type and display mode (Figures 6-4 and 6-5). Figure 6-6 shows a
  554.   hex and ASCII dump of part of the video map for the MDA.
  555.  
  556.   Display                  Background              Foreground
  557.   ──────────────────────────────────────────────────────────────────────────
  558.   No display (black)       000                     000
  559.   No display (white)
  560. VGA only
  561.       111                     111
  562.   Underline                000                     001
  563.   Normal video             000                     111
  564.   Reverse video            111                     000
  565.   ──────────────────────────────────────────────────────────────────────────
  566.  
  567.   Figure 6-4.  Attribute byte for 80-by-25 monochrome text display mode on
  568.   the MDA, Hercules cards, EGA, and VGA (IBM ROM BIOS mode 7).
  569.  
  570.   Value              Color
  571.   ──────────────────────────────────────────────────────────────────────────
  572.    0                 Black
  573.    1                 Blue
  574.    2                 Green
  575.    3                 Cyan
  576.    4                 Red
  577.    5                 Magenta
  578.    6                 Brown
  579.    7                 White
  580.    8                 Gray
  581.    9                 Light blue
  582.   10                 Light green
  583.   11                 Light cyan
  584.   12                 Light red
  585.   13                 Light magenta
  586.   14                 Yellow
  587.   15                 Intense white
  588.   ──────────────────────────────────────────────────────────────────────────
  589.  
  590.   Figure 6-5.  Attribute byte for the 40-by-25 and 80-by-25 text display
  591.   modes on the CGA, EGA, MCGA, and VGA (IBM ROM BIOS modes 0─3). The table
  592.   of color values assumes default palette programming and that the B or I
  593.   bit controls intensity.
  594.  
  595.   ──────────────────────────────────────────────────────────────────────────
  596.   B000:0000 3e 07 73 07 65 07 6c 07 65 07 63 07 74 07 20 07
  597.   B000:0010 74 07 65 07 6d 07 70 07 20 07 20 07 20 07 20 07
  598.   B000:0020 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07
  599.   B000:0030 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07
  600.   B000:0040 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07
  601.   B000:0050 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07
  602.   B000:0060 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07
  603.   B000:0070 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07
  604.   B000:0080 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07
  605.   B000:0090 20 07 20 07 20 07 20 07 20 07 20 07 20 07 20 07
  606.   ──────────────────────────────────────────────────────────────────────────
  607.  
  608.   Figure 6-6.  Example dump of the first 160 bytes of the MDA's regen
  609.   buffer. These bytes correspond to the first visible line on the screen.
  610.   Note that ASCII character codes are stored in even bytes and their
  611.   respective character attributes in odd bytes; all the characters in this
  612.   example line have the attribute normal video.
  613.  
  614.   You can calculate the memory offset of any character on the display as the
  615.   line number (y coordinate) times 80 characters per line times 2 bytes per
  616.   character, plus the column number (x coordinate) times 2 bytes per
  617.   character, plus (for the text/graphics adapters) the page number times the
  618.   size of the page (4 KB per page in 80-by-25 modes; 2 KB per page in
  619.   40-by-25 modes). In short, the formula for the offset of the
  620.   character-attribute pair for a given screen position (x,y) in 80-by-25
  621.   text modes is
  622.  
  623.     offset = ((y * 50H + x) * 2) + (page * 1000H)
  624.  
  625.   In 40-by-25 text modes, the formula is
  626.  
  627.     offset = ((y * 50H + x) * 2) + (page * 0800H)
  628.  
  629.   Of course, the segment register being used to address the video buffer
  630.   must be set appropriately, depending on the type of display adapter.
  631.  
  632.   As a simple example, assume that the character to be displayed is in the
  633.   AL register, the desired attribute byte for the character is in the AH
  634.   register, the x coordinate (column) is in the BX register, and the y
  635.   coordinate (row) is in the CX register. The following code stores the
  636.   character and attribute byte into the MDA's video refresh buffer at the
  637.   proper location:
  638.  
  639.   ──────────────────────────────────────────────────────────────────────────
  640.           push    ax          ; save char and attribute
  641.           mov     ax,160
  642.           mul     cx          ; DX:AX = Y * 160
  643.           shl     bx,1        ; multiply X by 2
  644.           add     bx,ax       ; BX = (Y*160) + (X*2)
  645.           mov     ax,0b000h   ; ES = segment of monochrome
  646.           mov     es,ax       ; adapter refresh buffer
  647.           pop     ax          ; restore char and attribute
  648.           mov     es:[bx],ax  ; write them to video buffer
  649.   ──────────────────────────────────────────────────────────────────────────
  650.  
  651.   More frequently, we wish to move entire strings into the refresh buffer,
  652.   starting at a given coordinate. In the next example, assume that the DS:SI
  653.   registers point to the source string, the ES:DI registers point to the
  654.   starting position in the video buffer (calculated as shown in the previous
  655.   example), the AH register contains the attribute byte to be assigned to
  656.   every character in the string, and the CX register contains the length of
  657.   the string. The following code moves the entire string into the refresh
  658.   buffer:
  659.  
  660.   ──────────────────────────────────────────────────────────────────────────
  661.   xfer:   lodsb               ; fetch next character
  662.           stosw               ; store char + attribute
  663.           loop    xfer        ; until all chars moved
  664.   ──────────────────────────────────────────────────────────────────────────
  665.  
  666.   Of course, the video drivers written for actual application programs must
  667.   take into account many additional factors, such as checking for special
  668.   control codes (linefeeds, carriage returns, tabs), line wrap, and
  669.   scrolling.
  670.  
  671.   Programs that write characters directly to the CGA regen buffer in text
  672.   modes must deal with an additional complicating factor──they must examine
  673.   the video controller's status port and access the refresh buffer only
  674.   during the horizontal retrace or vertical retrace intervals. (A retrace
  675.   interval is the period when the electron beam that illuminates the screen
  676.   phosphors is being repositioned to the start of a new scan line.)
  677.   Otherwise, the contention for memory between the CPU and the video
  678.   controller is manifest as unsightly "snow" on the display. (If you are
  679.   writing programs for any of the other IBM PC─compatible video adapters,
  680.   such as the MDA, EGA, MCGA, or VGA, you can ignore the retrace intervals;
  681.   snow is not a problem with these video controllers.)
  682.  
  683.   A program can detect the occurrence of a retrace interval by monitoring
  684.   certain bits in the video controller's status register. For example,
  685.   assume that the offset for the desired character position has been
  686.   calculated as in the preceding example and placed in the BX register, the
  687.   segment for the CGA's refresh buffer is in the ES register, and an ASCII
  688.   character code to be displayed is in the CL register. The following code
  689.   waits for the beginning of a new horizontal retrace interval and then
  690.   writes the character into the buffer:
  691.  
  692.   ──────────────────────────────────────────────────────────────────────────
  693.           mov     dx,03dah    ; DX = video controller's
  694.                               ; status port address
  695.           cli                 ; disable interrupts
  696.  
  697.                               ; if retrace is already
  698.                               ; in progress, wait for
  699.                               ; it to end...
  700.   wait1:  in      al,dx       ; read status port
  701.           and     al,1        ; check if retrace bit on
  702.           jnz     wait1       ; yes, wait
  703.  
  704.                               ; wait for new retrace
  705.                               ; interval to start...
  706.   wait2:  in      al,dx       ; read status port
  707.           and     al,1        ; retrace bit on yet?
  708.           jz      wait2       ; jump if not yet on
  709.  
  710.           mov     es:[bx],cl  ; write character to
  711.                               ; the regen buffer
  712.           sti                 ; enable interrupts again
  713.   ──────────────────────────────────────────────────────────────────────────
  714.  
  715.   The first wait loop "synchronizes" the code to the beginning of a
  716.   horizontal retrace interval. If only the second wait loop were used (that
  717.   is, if a character were written when a retrace interval was already in
  718.   progress), the write would occasionally begin so close to the end of a
  719.   horizontal retrace "window" that it would partially miss the retrace,
  720.   resulting in scattered snow at the left edge of the display. Notice that
  721.   the code also disables interrupts during accesses to the video buffer, so
  722.   that service of a hardware interrupt won't disrupt the synchronization
  723.   process.
  724.  
  725.   Because of the retrace-interval constraints just outlined, the rate at
  726.   which you can update the CGA in text modes is severely limited when the
  727.   updating is done one character at a time. You can obtain better results by
  728.   calculating all the relevant addresses and setting up the appropriate
  729.   registers, disabling the video controller by writing to register 3D8H,
  730.   moving the entire string to the buffer with a REP MOVSW operation, and
  731.   then reenabling the video controller. If the string is of reasonable
  732.   length, the user won't,even notice a flicker in the display. Of course,
  733.   this procedure introduces additional hardware dependence into your code
  734.   because it requires much greater knowledge of the 6845 controller.
  735.   Luckily, snow is not a problem in CGA graphics modes.
  736.  
  737. Graphics Mode
  738.  
  739.   Graphics-mode memory-mapped programming for IBM PC─compatible adapters is
  740.   considerably more complicated than text-mode programming. Each bit or
  741.   group of bits in the regen buffer corresponds to an addressable point, or
  742.   pixel, on the screen. The mapping of bits to pixels differs for each of
  743.   the available graphics modes, with their differences in resolution and
  744.   number of supported colors. The newer adapters (EGA, MCGA, and VGA) also
  745.   use the concept of bit planes, where bits of a pixel are segregated into
  746.   multiple banks of memory mapped at the same address; you must manipulate
  747.   these bit planes by a combination of memory-mapped I/O and port
  748.   addressing.
  749.  
  750.   IBM-video-systems graphics programming is a subject large enough for a
  751.   book of its own, but we can use the 640-by-200, 2-color graphics display
  752.   mode of the CGA (which is also supported by all subsequent IBM
  753.   text/graphics adapters) to illustrate a few of the techniques involved.
  754.   This mode is simple to deal with because each pixel is represented by a
  755.   single bit. The pixels are assigned (x,y) coordinates in the range (0,0)
  756.   through (639,199), where x is the horizontal displacement, y is the
  757.   vertical displacement, and the home position (0,0) is the upper left
  758.   corner of the display. (See Figure 6-7.)
  759.  
  760.     (0,0)┌─────────────────────────────────┐(639,0)
  761.          │                                 │
  762.          │                                 │
  763.          │                                 │
  764.          │                                 │
  765.          │                                 │
  766.          │                                 │
  767.          │                                 │
  768.   (0,199)└─────────────────────────────────┘(639,199)
  769.  
  770.   Figure 6-7.  Point addressing for 640-by-200, 2-color graphics modes on
  771.   the CGA, EGA, MCGA, and VGA (IBM ROM BIOS mode 6).
  772.  
  773.   Each successive group of 80 bytes (640 bits) represents one horizontal
  774.   scan line. Within each byte, the bits map one-for-one onto pixels, with
  775.   the most significant bit corresponding to the leftmost displayed pixel of
  776.   a set of eight pixels and the least significant bit corresponding to the
  777.   rightmost displayed pixel of the set. The memory map is set up so that all
  778.   the even y coordinates are scanned as a set and all the odd y coordinates
  779.   are scanned as a set; this mapping is referred to as the memory interlace.
  780.  
  781.   To find the regen buffer offset for a particular (x,y) coordinate, you
  782.   would use the following formula:
  783.  
  784.     offset = ((y AND 1) * 2000H) + (y/2 * 50H) + (x/8)
  785.  
  786.   The assembly-language implementation of this formula is as follows:
  787.  
  788.   ──────────────────────────────────────────────────────────────────────────
  789.                               ; assume AX = Y, BX = X
  790.           shr     bx,1        ; divide X by 8
  791.           shr     bx,1
  792.           shr     bx,1
  793.           push    ax          ; save copy of Y
  794.           shr     ax,1        ; find (Y/2) * 50h
  795.           mov     cx,50h      ; with product in DX:AX
  796.           mul     cx
  797.           add     bx,ax       ; add product to X/8
  798.           pop     ax          ; add (Y AND 1) * 2000h
  799.           and     ax,1
  800.           jz      label1
  801.           add     bx,2000h
  802.   label1:                     ; now BX = offset into
  803.                               ; video buffer
  804.   ──────────────────────────────────────────────────────────────────────────
  805.  
  806.   After calculating the correct byte address, you can use the following
  807.   formula to calculate the bit position for a given pixel coordinate:
  808.  
  809.     bit = 7 - (x MOD 8)
  810.  
  811.   where bit 7 is the most significant bit and bit 0 is the least significant
  812.   bit. It is easiest to build an 8-byte table, or array of bit masks, and
  813.   use the operation X AND 7 to extract the appropriate entry from the table:
  814.  
  815.   (X AND 7)          Bit mask          (X AND 7)          Bit mask
  816.   ──────────────────────────────────────────────────────────────────────────
  817.   0                  80H               4                  08H
  818.   1                  40H               5                  04H
  819.   2                  20H               6                  02H
  820.   3                  10H               7                  01H
  821.   ──────────────────────────────────────────────────────────────────────────
  822.  
  823.   The assembly-language implementation of this second calculation is as
  824.   follows:
  825.  
  826.   ──────────────────────────────────────────────────────────────────────────
  827.   table   db      80h         ; X AND 7 = offset 0
  828.           db      40h         ; X AND 7 = offset 1
  829.           db      20h         ; X AND 7 = offset 2
  830.           db      10h         ; X AND 7 = offset 3
  831.           db      08h         ; X AND 7 = offset 4
  832.           db      04h         ; X AND 7 = offset 5
  833.           db      02h         ; X AND 7 = offset 6
  834.           db      01h         ; X AND 7 = offset 7
  835.           .
  836.           .
  837.           .
  838.                               ; assume BX = X coordinate
  839.           and     bx,7        ; isolate 0─7 offset
  840.           mov     al,[bx+table]
  841.                               ; now AL = mask from table
  842.           .
  843.           .
  844.           .
  845.   ──────────────────────────────────────────────────────────────────────────
  846.  
  847.   The program can then use the mask, together with the byte offset
  848.   previously calculated, to set or clear the appropriate bit in the video
  849.   controller's regen buffer.
  850.  
  851.  
  852.  
  853.