Porting MS-DOS Graphics Applications

Are you hesitant about porting your favorite VGA MS-DOS program to Linux? Using this tutorial and SVGALIB, porting will truly become a matter of minutes.

I first started VGA programming under MS-DOS, using the popular DJGPP C compiler. In recent years, this protected-mode 32-bit compiler, which is basically an MS-DOS port of gcc, has established itself as one of the preferred compilers in the MS-DOS game programmers' community. DJGPP was in fact the MS-DOS compiler of choice for idsoftware's game Quake. For the Linux console port of Quake, the Linux Super VGA library, SVGALIB was used.

When I first decided that I was going to port my own 3-D Model Viewer, jaw3d, from MS-DOS to Linux, it seemed logical to use the same approach. SVGALIB is very intuitive and allows me to easily maintain and further develop my 3-D Model Viewer for both platforms.

I found the easiest way to work with one set of source files for both platforms was to use preprocessor directives in places where different code was needed. Since I had already written and used DJGPP's low-level VGA and mouse instructions for the MS-DOS version, I simply added the equivalent SVGALIB Linux code in each instance, and separated the MS-DOS and Linux code using the preprocessor directive #ifdef. The following code snippet represents one of the many ways in which this can be accomplished:

#ifdef __DJGPP__
...
...
#endif
#ifndef __DJGPP__
...
...
#endif

__DJGPP__ is automatically defined by the DJGPP compiler, and is not defined by gcc under Linux.

An additional advantage of using SVGALIB under Linux is the fact that there is also a DJGPP version of SVGALIB. Let's try not to get confused at this point: SVGALIB is a graphics library that does some behind-the-scenes low-level VGA and mouse work for the user. Although SVGALIB was first developed for Linux, someone eventually released a version that worked with DJGPP under MS-DOS. Why not use SVGALIB for both MS-DOS and Linux? This would allow us to have 100% identical code for both platforms.

I don't recommend this approach, however, for two reasons. First, when I made speed comparisons of my 3-D engine between the two platforms, I noticed that when using SVGALIB with DJGPP under MS-DOS, graphics performance was sluggish in comparison with SVGALIB under Linux. Second, the MS-DOS executable was unnecessarily big because it had to be statically linked with the SVGALIB library. Using SVGALIB under Linux did not seem to present any problems. Due to the use of shared libraries under Linux, the executable remained tiny when dynamically linked, and graphics performance was actually slightly better under Linux than under MS-DOS. For the sake of performance and executable size, I found it best to use DJGPP's low-level instructions under MS-DOS and to use SVGALIB under Linux. This makes a difference, especially in a setting like 3-D engines, where every frame-per-second counts.

The advantage obtained from using the DJGPP port of SVGALIB is the fact that you can test your SVGALIB Linux code under MS-DOS, without having to reboot. Except for speed and executable size, both versions of SVGALIB behave identically.

Note that the DJGPP port of SVGALIB is still in beta, but I ran across only one minor problem and that was easily fixed. The file vgakeybo.h included with the DJGPP port of SVGALIB seemed to differ from the file vgakeyboard.h under Linux; therefore, making cross compilations was impossible in cases where keyboard code was used. The two files should be identical, of course, and the solution is to copy the Linux version of the include file over the DOS one.

The three compiler-specific code aspects are VGA, mouse input and keyboard input. If you have completed an MS-DOS graphics application, you may be using much of this code already and can quickly add on the SVGALIB equivalent code. On the other hand, if you do not have any previous graphics programming experience, you will find the code shown in Listings 1 through 4 to be very useful.

Listing 1. Include Files

Listing 2. Initializing the VGA Mode

Listing 3. Keyboard Code

Listing 4. Mouse Code

Copying a Buffer to Video

In the case of my 3-D Model Viewer, jaw3d, a complete frame is first rendered onto a buffer which has the same dimensions as the screen, and then copied to video memory all at once, allowing us to display frequently updated screens successively without any flickering. This is done as follows:

        memcpy (video_buff, image_buffer,
                DIM_X * DIM_Y);
        /* video_buff was initialized above */
        dosmemput (image_buffer, DIM_X * DIM_Y,
                0xA0000);
        /* 0xA0000 is the video memory in VGA mode
         * 13h */
______________________

Webinar
One Click, Universal Protection: Implementing Centralized Security Policies on Linux Systems

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Learn More

Sponsored by Bit9

Webinar
Linux Backup and Recovery Webinar

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.

Learn More

Sponsored by Storix