We ❤️ Open Source
A community education resource
Intro to DOS graphics: A simple way to draw with pixels
One neat trick that's easy in DOS but surprisingly tricky in Linux.
I like programming! It’s something I do for fun: To experiment, to tinker, or to explore new ideas. While I enjoy the many powerful tools available on Linux that make it easy to write new programs, I also appreciate the simplicity of writing programs for DOS.
If you don’t know, DOS was the Disk Operating System for PCs in the 1980s and early 1990s. I was in my teens during that time, and that’s where I explored programming. The DOS command line wasn’t very powerful, but if you knew a little about programming, you could create your own tools so you could do more work from the command line. And that’s exactly what I did.
I also loved the many DOS applications that let me do all kinds of work, like writing class papers in a word processor, or analyzing my physics lab data in a spreadsheet when I was an undergraduate student. But it was the ability to easily create new programs that really drew me to DOS programming.
I’d like to share one neat thing you can do with DOS programming that is easy to do in DOS but hard to do in Linux.
Read more: FreeDOS 1.4 is the retrocomputing system you’ve been waiting for
Displaying graphics
If you want to write a Linux program to display something in graphics mode, like a program that draws a picture inside a window, you need to load a lot of supporting libraries. For example, to write a program in GNOME, you need to initialize the toolkit, then define a new window, then set the title, size, and position. To draw within this window also requires defining a canvas and connecting to it so the program can add other elements.
In DOS programming, all programs start in console mode by default. A program can enter a graphics mode using a function, like Open Watcom’s _setvideomode, and specify a resolution, such as _VRES16COLOR for 640×480 at 16 colors. That’s it! Just one function to start displaying graphics in DOS.
#include <stdio.h>
#include <graph.h> /* graphics */
int main()
{
if (_setvideomode(_VRES16COLOR) == 0) { /* 640x480 */
puts("cannot set video mode");
return 1;
}
/* add other stuff here */
_setvideomode(_DEFAULTMODE);
return 0;
}
This simplicity makes it very easy to experiment. Let’s explore one way to use graphics mode by drawing a special kind of triangle.
Read more: 5 FreeDOS editors I love
Painting with pixels
Sierpinski’s Triangle is a fractal image that you can generate by drawing a series of random pixels to the screen. The rules are simple: Define three corners of the triangle. Start at any random point on the screen. Then iterate by drawing a new dot or pixel halfway between the current dot and a random corner of the triangle. You’ll see Sierpinski’s Triangle emerge from this random collection of points.
The _setpixel function in Open Watcom paints a single pixel to the screen, at whatever x,y coordinate you give it. Coordinates start from zero. That means in _VRES16COLOR mode, the x coordinates range from 0 to 639, and y coordinates are from 0 to 479. You can set the pixel’s color with _setcolor. The _VRES16COLOR mode has 16 colors, so color numbers are between 0 (black) and 15 (bright white).
Let’s use these two functions to draw a pixel at a random coordinate on the screen, in a random color:
#include <stdio.h>
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
#include <conio.h> /* kbhit, getch */
#include <graph.h> /* graphics */
int main()
{
short x,y;
/* set video mode */
if (_setvideomode(_VRES16COLOR) == 0) { /* 640x480 */
puts("cannot set video mode");
return 1;
}
/* random x,y */
srand(time(NULL));
x = rand() % 640; /* 0 .. 639 */
y = rand() % 480; /* 0 .. 479 */
_setcolor(rand() % 16); /* 0 .. 15 */
_setpixel(x,y);
if (getch() == 0) { getch(); }
/* done */
_setvideomode(_DEFAULTMODE);
return 0;
}
DOS doesn’t support a kernel-level random number generator; Linux has a getrandom system call, but DOS programs need to use the rand standard library function to generate pseudo-random numbers between 0 and some large maximum value. Seed the random number generator with srand with a number, such as the current time with the time function.
After that, the program uses _setcolor to pick a random color from 0 to 15, then _setpixel to draw a dot at a random coordinate on the screen.

The program also waits for the user to press a key before it exits. The getch function gets a single keystroke and returns its value; since DOS keyboards also have extended keys like F1, Home, End, and other keys, getch will return zero if the user pressed an extended key. In that case, the program needs to call getch one more time to get the extended value. That’s why the program calls getch twice if the first function was zero.
Read more: How to write your first FreeDOS program
Random pixels to draw a triangle
That’s not a very interesting program, but it’s a good start. Let’s add to the program by defining the corners of a triangle on the screen, at 320,0 (centered at the top of the screen) and 50,479 and 590,479 (at the bottom of the screen). To make it easier to refer to these later, we’ll define them in an array of three values, where each value is an x,y coordinate:
struct { short x; short y; } corner[3] = {
{320,0}, {50,479}, {590,479} };
We’ll draw the first pixel in black, at a random coordinate on the screen, and each successive pixel in a color from 1 (dark blue) to 15 (bright white). Each time the program draws a pixel, it places it halfway between that dot and a random corner of the triangle.
#include <stdio.h>
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
#include <conio.h> /* kbhit, getch */
#include <graph.h> /* graphics */
int main()
{
struct { short x; short y; } corner[3] = {
{320,0}, {50,479}, {590,479} };
short x,y;
short c;
int n, key;
/* set video mode */
if (_setvideomode(_VRES16COLOR) == 0) { /* 640x480 */
puts("cannot set video mode");
return 1;
}
/* random start x,y */
srand(time(NULL));
x = rand() % 640; /* 0 .. 639 */
y = rand() % 480; /* 0 .. 479 */
/* iterate */
c = 0;
do {
_setcolor(c);
_setpixel(x,y);
/* next value halfway between x,y and any corner */
n = rand() % 3; /* 0 .. 2 */
x = (x + corner[n].x) / 2;
y = (y + corner[n].y) / 2;
if (++c > 15) { c = 1; } /* rotate color */
if (kbhit()) {
key = getch();
if (key == 0) { getch(); } /* ext key */
}
} while ((key != 27) && (key != 'q') && (key != 'Q'));
/* done */
_setvideomode(_DEFAULTMODE);
return 0;
}
This new version of the program adds the kbhit function, which returns a true value if the user has pressed a key. If so, then the program uses getch to read the keystroke. The program continues in an infinite loop until the user presses the Q key or the Esc key. The Esc key has the value 27.

Explore DOS programming with FreeDOS
If you want to explore DOS programming, I encourage you to download and install FreeDOS. The FreeDOS 1.4 distribution includes lots of programming tools, provided on the Bonus CD, so you can create your own DOS programs. For example, I used the Open Watcom C compiler to write this program.
I like writing programs like this in FreeDOS because using graphics mode is so easy in DOS. Whenever I need to write a program to visualize something, I usually do it in graphics mode on DOS. With just one function call to set up graphics mode, it’s hard to beat the simplicity to make a quick prototype.
More from We Love Open Source
- 5 FreeDOS editors I love
- How to write your first FreeDOS program
- FreeDOS 1.4 is the retrocomputing system you’ve been waiting for
- Explore the five steps of the FreeDOS boot sequence
- A throwback experiment with Linux and Unix
The opinions expressed on this website are those of each author, not of the author's employer or All Things Open/We Love Open Source.