Mode 13h is so widely used for graphics applications in DOS because it
is very easy to use. The screen is constantly being redrawn by the
video card. To affect what the card draws, it is necessary to write to
the screen buffer. The screen buffer in mode 13h is always at
segment:offset = A000:0000. Thus, to set up drawing directly to the
video buffer, this is what you’d most often first do:
123456789
;Change the video mode to 13hxorah,ah;VIDEO Function 00h: Change screenmoval,13h;Put the desired graphics mode into ALint10h;Call VIDEO;Prepare for writing to the video buffermovdi,0a000h;Put the video segment into DImoves,di; so it can easily be put into ESxordi,di;Start writing at coordinates (0,0)
12.2 WRITING PIXELS TO THE SCREEN
Why is Mode 13h so popular? To understand, you must know a few basic
facts. In Mode 13h, the screen is 320 by 200, or 320 pixels across and
200 pixels down. In each pixel, there’s a possibility of 256 colors,
which can be fit into one byte. Thus, 3202001 = 64000 bytes, about
the size of one segment. Think of the screen as an array of colors.
The first row takes up addresses A000:0000 to A000:013F (decimal 319),
the second row takes up addresses A000:0140 to A000:027F (decimal 639),
and so on. To plot a pixel, assuming ES=A000:
1234567891011
;Plot a pixel in video mode 13h, where;PixelAddress = (320 * Y) + Xmovax,320; Prepare for the multiplicationmul[Y]; Assuming that Y is defined in the data segment; earlier in the programmovdi,ax; Put in into the pointer to the offset of ESadddi,[X]; Assuming that X is defined in the data segment; earlier in the programmoval,[Color]; Assuming that Color is defined in the data; segment earlier in the programstosb; Write it to the screen!
See how easy that was? Something to remember is that it is zero-based.
The upper-left corner is (0,0), and the lower-right is (319,199). A
complete TASM Ideal mode procedure might look something like this (it
assumes that the video card is already set to mode 13h):
1234567891011121314
PROCWritePixelBASIC; Or whatever language you might want to link; it toUSESes,di; It's always a good idea to preserve ES and DIARGX:word,Y:word,Color:BYTEmovdi,0a000h; Put the video segment into DImoves,di; so it can easily be put into ESmovax,320; Prepare for the multiplicationmul[Y]; Offset pointer by the Y value passed inmovdi,ax; Put in into pointer to the offset of ESadddi,[X]; Offset the pointer by the X value passed inmoval,[Color]; Put color to be written to the screen in ALstosb; Write it to the screen!retENDPWritePixel
To write a horizontal line, just put the length in CX, and replace the
STOSB with a REP STOSB. Writing a vertical line is only a little
trickier. Observe the following TASM Ideal mode procedure:
123456789101112131415161718192021
PROCVerticalLineBASIC; Or whatever language you might want to link; it toUSESes,di; It's always a good idea to preserve ES and; DIARGX:word,Y:word,Color:BYTE,Length:wordmovdi,0a000h; Put the video segment into DImoves,di; so it can easily be put into ESmovax,320; Prepare for the multiplicationmul[Y]; Offset the pointer by the Y value passed inmovdi,ax; Put in into the pointer to the offset of ESadddi,[X]; Offset the pointer by the X value passed inmoval,[Color]; Put the color to be written to the screen; in ALmovcx,[Length]; Prepare for the loopYLoop:stosb; Write it to the screen!adddi,319; Move down one row (DI has already advanced; once because of the STOSB, thus the 319)loopYLoopretENDPVerticleLine
Observe how there is a tight loop that moves DI down one row each
iteration.
In short, the easiest way to write directly to the Mode 13h video buffer
is to think of the screen as just a 320 by 200 array of bytes, starting
at A000:0000.
Author: Michael Averbuch (mikeaver@prairienet.org)
Last Change: 29 Dec 94