Wallpaper for DOS
For a short time (two months), I wrote a DOS column for the now defunct net-zine, PCSense. My last article was submitted for the February 1996 issue, but it was never published. So, just for grins, I'm adding it to my personal web site.

Writing for PCSense is fun, but I make a living as a consulting electronics engineer. In that capacity, I use a lot of engineering software that is not likely to be rewritten for Windows. I also find Window's resource requirements to be too demanding sometimes. So, though I use Windows, I don't plan on giving up on DOS. I wonder how many others have similar reasons for staying with DOS.

Recently, I was reflecting on what makes Windows so popular and came to the conclusion that it's because DOS is missing pretty wallpaper (well, maybe a little more than that). Just for fun I decided to add some wallpaper to fill this void. It's pretty easy with a trick I picked up back in the days of the original IBM PC. That is, to write directly to the character display area of video memory. It still works with today's video boards, even though they differ greatly from the original Color Graphics Adapter. It even works in Windows.

At first glance, it would seem that DOS lacks a utility that can write directly to video memory, but surprisingly its easy to do with the DEBUG program. In fact, the code to paint the screen is nearly trivial. A single DEBUG Fill command does it in the blink of an eye. Unfortunately, DEBUG is an arcane, old programmer's tool, that requires the user to wrestle with hexadecimal numbers. However, the extra effort makes some rather amazing things possible.

For example, to paint the screen with gray shading on a blue background only requires the following single command at the DEBUG hyphen prompt:

-F B800:0 L 1F40 B0 18
Let's work from left to right to understand it. The F designates the fill command. The next parameter specifies the starting memory address for the fill, in hexadecimal format. The address, B800:0, is the beginning of the text portion of the video memory. Next, the L specifies that a length parameter is being provided as opposed to giving an ending memory address. The value 1F40 is the hexadecimal equivalent of a length of 8000 bytes. This is the number of bytes needed to fill a VGA adapter's 50 line text display. A 25 line display requires half as many bytes, but the extra bytes ensure compatibility with either display mode. The next parameter, B0, is the code for one of the extended ASCII characters commonly used to make a shaded background. It is the character you see when you hold the ALT key and then press 1, 7 and then 6 on the numeric keypad.

The last entry in the example defines the color attribute byte to be used in filling the video display. The first character defines the background color, while the second specifies the foreground color. On a normal display, the non-blinking background colors are specified between 0 and 7 and the foreground colors run from 0 to F, the letters A through F being the hexadecimal digits that equal the decimal numbers 10 through 15. The colors for each number are shown in Figure 1. Background colors greater than 7 cause the characters to blink as long as a full screen DOS display is used. Under Windows, a DOS session displayed in a window will not blink. Rather, it displays high intensity background colors.

Figure 1. The sixteen foreground colors in text mode.
Clearly, an easy way to automate the process of loading the display memory is needed for this knowledge to be of general use. The batch file, FULL.BAT, does just that.
:: FULL.BAT - A routine to paint a pattern of characters to the
::            full screen.
:: Tom Lavedas <lavedas@pressroom.com> :: http://www.pressroom.com/~tglbatch/ @echo off if [%1]==[] %0 20 18 if [%2]==[] %0 %1 18 set {t}=FB800:0L1F40 %1 %2 :Loop if not [%4]==[] for %%v in (set shift shift goto:Loop) do %%v {t}=%{t}% %3 %4 > {s} echo %{t}% >>{s} for %%v in (echo.q set) do %%v {t}= < {s} debug > nul del {s}
Calling FULL with a list of character/color pairs loads the video memory with repetitions of that sequence. The only limitation is that the sequence must fit within DEBUG's 80 character line limit, less the fill command's 14 character overhead. An arbitrary number of characters can be supplied as command line arguments. The character and color attributes values are collected into the environment variable, {T}, by the ":Loop" label and the FOR statement that follows it. The FOR statement is actually a little subroutine that executes four statements for each pass. The string in {T} is then used in making the two line script stored in the file {S}. The script contains the complete DEBUG fill command and a quit command (Q) to exit the DEBUG program. Redirecting this script into DEBUG is all that's needed to paint the character pattern.

The second noncomment line of the batch file supplies default values so that FULL can be called without arguments. In that case, the screen is simply cleared to a blue background. The third line adds a default color if none is defined on the command line. Note that the ANSI.SYS driver need not be loaded.

It is surprisingly easy to create interesting background patterns with just a few characters. Patterns that divide evenly into 80 draw stripes, while those that don't result in diagonal lines or checkered patterns. For example, the following FILL creates a red, white and blue checkered pattern.

FULL B2 41 B1 17 B2 14
The pattern description in the example uses hexadecimal character definitions, but DEBUG permits characters enclosed in single or double quotes as well. For example, the following example created the display shown in Figure 2.
FULL 'P'1F'C'1E'S'1D'e'1C'n'1B's'1A'e'19 20 1E 20 1E
Each letter is followed by a color attribute byte. The single quote mark acts as a delimiter in DEBUG, but not in the batch file argument. So, the previous FILL command really has only five arguments. The last two character arguments are hexadecimal representations of the space character. The hex representation is used because batch file delimiters (space, semicolon, comma, equal and tab) must be entered as their hex equivalents to work properly. In general, it is safer (but not always easier) to use the hex representation.

Figure 2. An example created with FULL.BAT.
A few modifications to FULL.BAT gives a more versatile procedure, FILL.BAT, that has the option of either filling the whole screen or just part of it. This procedure takes two additional arguments; %1, the offset to the first video address and %2,the number of bytes to be written. Thus, the definition of character/color pairs begin with the third command line entry. As with the FULL.BAT procedure, default values are provided. In fact, when no parameters are provided it works the same as FULL. However, there are up to four possible default conditions for the FILL.BAT routine. Each one is tested and an appropriate value is provided if an argument is missing.

FILL.BAT also displays a reference table to assist in determining the hexadecimal starting address of a row or the number of bytes needed to paint a number of rows. There is one line in the reference table for every ten rows possible on the VGA text display. Each row shows ten addresses for rows ending with the digits 0 through 9. For example, the starting address for row 24 (F00 hex) is shown in the 2_ row of the table, under the column headed by the digit 4. The reference table is displayed when the first input value is a question mark.

:: FILL.BAT - A routine to paint a pattern of characters to the
::            screen.
:: Tom Lavedas <lavedas@pressroom.com> :: http://www.pressroom.com/~tglbatch/ @echo off if not [%1]==[?] goto Start :: { Help } echo. echo. Hexadecimal Values for Rows on a VGA Text Display echo. +----+---------------------------------------------------+ echo. :Row : 0 1 2 3 4 5 6 7 8 9 : echo. :----+---------------------------------------------------: echo. : 0_ : 0 A0 140 1E0 280 320 3C0 460 500 5A0 : echo. : 1_ : 640 6E0 780 820 8C0 960 A00 AA0 B40 BE0 : echo. : 2_ : C80 D20 DC0 E60 F00 FA0 1040 10E0 1180 1220 : echo. : 3_ : 12C0 1360 1400 14A0 1540 15E0 1680 1720 17C0 1860 : echo. : 4_ : 1900 19A0 1A40 1AE0 1B80 1C20 1CC0 1D60 1E00 1EA0 : echo. +----+---------------------------------------------------+ echo. goto End :: :Start if [%1]==[] %0 0 1F40 20 18 if [%2]==[] %0 %1 1F40 20 18 if [%3]==[] %0 %1 %2 20 18 if [%4]==[] %0 %1 %2 %3 18 set {t}=FB800:%1L%2 %3 %4 :Loop - { Collect the pattern to be displayed } if not [%6]==[] for %%v in (set shift shift goto:Loop) do %%v {t}=%{t}% %5 %6 > {s} echo %{t}% >>{s} for %%v in (echo.q set) do %%v {t}= debug < {s} > nul del {s} :End - { Clean-up and exit }
Finally, the batch file GREETING.BAT is provided below as a lighthearted illustration of how you might use FULL and FILL. The procedure paints different greetings on the screen in response to each of five predefined selections: Goodday, February, March, July or December. However, you can make up your own greeting by supplying a background character, three color attributes and a message. Use the defaults as a pattern for creating your own. Oh! And be sure to view the July greeting full screen (Celebrates US Independence Day).
:: GREETING.BAT - A demonstration of painting the screen in DOS. :: Updated Mar 2000 :: Tom Lavedas <lavedas@pressroom.com> :: http:://www.pressroom.com/~tglbatch/ @%dbgg% echo off if '%1==' %0 GoodDay - // default message // for %%v in (0 GoodDay 2 Feb February 3 Mar 7 July 12 Dec December) do set _%%v= set _%1=%1 :: // Check for predefined messages // :: -Colors- :: Chr %2 %3 %4 ---- Message -------------- if '%1=='%_0%%_goodday% %0 01 1E 11 11 Have a Good Day if '%1=='%_2%%_feb%%_february% %0 03 14 15 1C Happy Valentine's Day if '%1=='%_3%%_mar%%_march% %0 05 72 77 7A Happy Saint Patrick's Day if '%1=='%_7%%_July% %0 0F F4 F1 1F Born on the Fourth of July if '%1=='%_12%%_dec%%_december% %0 0F 4F 24 22 * * * Merry Christmas * * * for %%v in (0 GoodDay 2 Feb February 3 Mar 7 July 12 Dec December) do set _%%v= mode con lines=50 cls :: // Paint the screen // :: CALL FULL %1 %2 %1 %3 %1 %4 :: CALL FILL 960 C80 B1 %4 :: set {m}=%5 :Loop - // Collect the entire message to be displayed // if not '%6==' for %%v in (set shift goto:Loop) do %%v {m}=%{m}% %6 :: // Display the message // for %%v in (1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4) do echo. echo %{m}% for %%v in (1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ) do echo. :End - // Clean-up and exit // for %%v in (set pause) do %%v {m}=

Figure 3. A Valentine's Day Greeting made with GREETING.BAT
If you would like to download the three batch files, plus the procedure used to create the color reference table in Figure 1, they are available as a self-extracting zip file, d4batch.exe.

Tom Lavedas

Have fun and feel free to send me some of your creations.


Related subjects (links) to be added in the future (maybe):
  • Bulk reads and Writes to the screen
  • Moving around the screen without ANSI.SYS



  • Top | General Notes | Homepage