Mode 13h is a standard VGA graphics mode. While it may seem somewhat limited in resolution and colors when compared to SVGA modes, it is supported on nearly every computer available today. There are 320 pixels over and 200 pixels down the screen, each of which may have one of 256 colors. Mode 13h is unique from other higher-resolution, but only 16-color, VGA graphics modes because the memory for the video screen is arranged linearly, where one byte corresponds to one pixel on the screen. As a result, Mode 13h is very easy to program in since it's not necessary to deal with bit planes.
The first step to making a Mode 13h program is to call a BIOS interrupt to enter it. Do this by:
mov ax, 0013h
int 10h
To return back to text at the end of the program, use:
mov ax, 0003h
int 10h
Once in Mode 13h, each pixel can be set to any color from a palette of 256 colors. There are two methods to do this by--using BIOS interrupts or direct writes. Direct writes are the best choice here due to the simplicity of Mode 13h (the bit planes used in other VGA modes can make BIOS interrupts the best choice). Since each pixel directly corresponds to one byte, just set the byte to the color (0 - 255). Use the following formula to determine the address and move a byte into it:
The following code fragment illustrates how to set a pixel:
; Before drawing graphics
mov ax, 0A000h ; Set ES to graphics screen segment
mov es, ax
|
(set X and Y and DL to the color)
|
mul di, [Y], 320 ; Multiply Y by 320 and store in DI
add di, [X] ; Add the X coordinate
mov [es:di], dl ; Set the pixel to the color specified
; by DL
This method can be much faster than BIOS, because for most things, only a few MUL instructions should be needed and the majority of pixels can be set by moving relative to the original address. For example, to move left or right, simply subtract or add 1 from the address, and to move up and down, subtract or add 320, respectively. Use this method along with string operations to set entire ranges, draw straight horizontal and vertical lines, and draw boxes. For more information about string operations, refer to Section 4.6.
One of the most aggravating thing about creating animated images is the flicker and delays seen by the user while the image is being drawn. Because of Mode 13h's memory scheme and usage, it is possible to draw the graphics on another segment in memory instead of the graphics screen, and when an individual frame is finished being created, to copy that segment directly onto the VGA screen memory. The easiest and fastest way to do this is to use string operations.
To create a blank segment in the program that graphics instructions can be "redirected" to, do the following:
SEGMENT ScratchSeg ScratchPad resb 64000
This should be included at the beginning of the program along with other segment definitions. Then, instead of setting ES to point to the VGA memory segment, have ES point to the ScratchSeg segment when plotting pixels.
Once an entire frame has been drawn on the scratch segment, it is very simple to copy it to the VGA screen:
mov ax, ScratchSeg ; from scratch segment
mov ds, ax
mov ax, 0A000h ; to graphics screen
mov es, ax
cld ; set direction flag forward
mov esi, ScratchPad ; set the source offset
xor edi, edi ; dest. offset will always be 0
mov ecx, 320*200/4 ; 320*200, copying doublewords
rep movsd
This will issue a MOV command 16,000 times, each time moving a DWORD (4 pixels) from the ScratchSeg segment to the VGA screen.
Note: Each segment declared in this fashion occupies 64k = 64000 bytes of memory. Real mode only allows 640k of total memory, so only declare at most 2 or 3 scratch segments.