640 KB is really enough for everyone / Habrahabr

January 8, 2018
110 Views
 image

Never give up

Did Bill Gates really say "640 KB should be enough for everyone"? Her story is rather vague, but most often it is attributed to Bill, so maybe he really said that.

He was often ridiculed for that. The idea of ​​a common memory space of only 640 KB in size by modern standards is ridiculous. In this size, even the executable files of most installers will not fit.

For comparison: the calculator in Windows 10 is idle 16.2 MB RAM – almost 26 times more than the amount of available DOS-program memory in the 1980s.

Strange things

Will you believe me if I say that there is still an active community using this outdated platform and developing software for it?

Perhaps your first question will be "But why?" And I understand you well. Let's look at some of the groups that are still interested in investing in DOS.

Legacy Systems Developers

Today, there are still many programs that run in DOS . Industrial control programs, point-of-sale systems and scientific tools are just some of the examples of applications where even DOS is used today. Over time, most of these programs have been ported to other systems or completely rewritten, but some still survive.

The non-cost real-time system

DOS is essentially the real-world operating system time (RTOS). It was not specifically designed for this purpose, but its minimalistic design allows it to be related to other similar systems.

The RTOS is characterized by a predictable delay in software and hardware requests. Since DOS has a minimal API without internal multitasking, the stability of the operating system call delays is quite high.

Although there are already more recent examples of real-time systems with improved design and designed specifically for this purpose, the finest DOS interface between the application and the equipment gives it an advantage in this area of ​​use. Since such systems as FreeDOS (which I'll discuss below) have open source and are distributed free of charge, they are a good alternative to other RTOS.

Nostalgic video games

Modern video games are terrific. They require huge 3D power, but graphics, sound and gameplay are sometimes so realistic that they can be confused with reality. Virtual reality equipment further reinforces this sensation, allowing players to fully immerse themselves in the game environment.

But despite all this progress, many gamers who were children in the 80s and early 90s remember with love the times, graphics and synthesizer sounds forced them to fill in the blanks with their own imagination.

Despite the fact that the equipment left the DOS era limitations far behind, there is still an active scene of DOS gamers. Moved by nostalgia and a love of programming, developers write games that run on older systems, including those on PCs that were originally shipped from DOS.

If you think this market is limited to a handful of retirees trying to get back to their technological childhood, then you are mistaken. David Murray, more known in YouTube as The 8-bit Guy, has more than half a million subscribers who explore the territory of nostalgic computer hardware every week. He even wrote a real-time strategy for the Commodore 64 called PlanetX2. The project was so successful that David sold out all the physical stocks of the players with the game and plans to create a sequel to the DOS platform.

Start DOS

There are many ways to start DOS. Perhaps you even have a computer on which you can start it right now. But since we want to work closely with this operating system, we will use the way in which free software is used that works on almost any computer.

First, let's talk a little about the license. According to some information, Microsoft has made MS-DOS 6.22 public domain, but I could not find this confirmation. Because the software can be easily downloaded from fairly secure online sources, I'm not in favor of installing something that might violate copying rights. Even if you have a legally acquired copy (and I suspect that it is for many), installing it on a virtual machine can be a legally risky act.

To simplify the installation, we will use FreeDOS. FreeDOS is a DOS clone with open source, written by Jim Hall. Jim began development in June 1994, when Microsoft announced that it would no longer sell and support MS-DOS. A few weeks later Pat Villany and Tim Norman joined the project. Just a few months later, version 0.01 appeared. Today we are using version 1.2, released on Christmas Day 2016.

First we go to the FreeDOS website and download the ISO image of the standard installer on the CD-ROM. You can also download the USB version, but with differences in hardware, BIOS, etc. we will not consider this method here. Instead, we will use virtualization.

I tested FreeDOS with both VirtualBox Oracle and with VMware Workstation / Player. Both products work well, but VMware provides slightly better BIOS emulation and implements the PC speaker used in many games for DOS. In the examples below, I will use VMware Workstation, but in principle any system will do it.

By default, the installation options for FreeDOS are VirtualBox and VMware. You may be surprised how little RAM and disk space is allocated. Normally, I create a 2GB disk for DOS, but the default 512 MB will be enough.

FreeDOS installation is simple, it's enough to boot into the virtual machine from an ISO image (an ISO file request will be issued at startup or when creating a virtual machine) and follow the on-screen prompts. After FreeDOS crashes the disk and reboots, select "Install to Hard Disk" again. Choose "Full Installation" or "Full Installation with Sources" if you like to see how things work. You are reading this article, so most likely it is, then why not install the sources?

After installation, you will need to reboot. This time, instead of selecting "Install to Hard Disk" in the boot menu of the CD, select "Boot from System Hard Disk". The default Jemmex option (with no EMS) is quite suitable for standard downloads, especially if you want to do development.

Technically, the FreeDOS system is ready to work, but it's still completely naked. In this state it is convenient to run games and DOS programs, but it is not entirely suitable for development, because we do not have important tools.

Cute FDimples

Now it's time to install some software in FreeDOS. OS contains a wonderful system of management packages FDimples. To use it, type:

  fdimples  

On this screen you can install a wide range of software. Here we have two options – to install all development tools, or just to install everything. The second option may seem like an exhaustive search, but remember that according to modern standards all these programs will take up very little space, so the disk will still have a lot of space.

A stunning package manager with a cute name .

You can use the arrow keys to move between categories and packages. A space is selected for individual packages, ENTER – whole categories. Whatever option you choose, be sure to check the Development category. To start the installation, press TAB until the OK button is selected, then press ENTER.

C ++ does not hide

But you do not aspire, do you? C ++ is remarkable, and thanks to DJ Delory, the performance and capabilities of the GNU Compiler Collection are now available in DOS.

Moreover, with the included DOS extender CWSDPMI, programs can use protected mode and compile into 32-bit executable files without the slightest problem . You can overcome the barrier of 640 KB with a large margin. Bite, Mr. Gates!

To test the working environment of the development environment, let's create a new folder and test project:

  mkdir C:  src
mkdir c:  src  hello
rhide c:  src  hello  hello.cpp  

This will launch the RHIDE development environment. It does not reach the level of Visual Studio, but for our needs, development is quite sufficient. It reminds me of the Borland Turbo-C environment, which is associated with a lot of pleasant memories.

This warmth spreads through the body and runs the creeps.

test code:

  #include 
using namespace std;

int main () {
  cout << "Hello, World!  n";
  return 0;
}  

Now you can start the code using the "Run" menu (or by pressing ALT + R, then R or CTRL + F9). You will notice that you can use the mouse and hot keys. At first, the mouse is enough, but remember the hot keys that are listed next to the various menu items. After spending some time in RHIDE, you will remember the most important of them and your productivity will increase significantly!

A more interesting example

Let's do something more interesting. First, let's create a workspace:

  mkdir c:  src  example
rhide c:  src  example  example.cpp  

In this example, we show how video modes are set, pixels are specified, and color management is performed in VGA mode 320x200x256.

  #include 
#include 
#include 
#include 
#include 
#include 
#include 
 
#define COLOR_WHITE 15
#define MAX_WIDTH 320
#define MAX_HEIGHT 200

using namespace std;

void set_video_mode (int mode) {
  // Create a structure for registers
  __dpmi_regs r;
 
  // Set AX to the video mode value
  r.x.ax = mode;
 
  // Call int 10 (set the video mode of the BIOS)
  __dpmi_int (0x10, & r);
}

void put_pixel (int x, int y, int c) {
  // Video VGA is at A000, so let's write to it.
  _farpokeb (_dos_ds, 0xA0000 + y * 320 + x, c);
}

void clear_pixel (int x, int y) {
  // We just write pixel 0 to clear the point
  _farpokeb (_dos_ds, 0xA0000 + y * 320 + x, 0);
}

void draw_effect () {
  // Current x and y coordinates
  int x = 0;
  int y = 0;

  // For each up to y_max write a pixel
  for (y = 0; y <MAX_HEIGHT, y ++) {
    for (x = 0; x <MAX_WIDTH, x ++) {
      put_pixel (x, y, rand ()% (15 + 1));
    }
  }
}

int main () {
  // Set the video mode to 13h (320x200x256)
  set_video_mode (0x13);

  // Draw the effect
  draw_effect ();

  // Wait for the ENTER key to be pressed
  cin.ignore ();

  // Go back to text mode
  set_video_mode (3);

  return 0;
}  

The example of the movement

In this example, based on the previous example, we add a user-driven motion. We will use the arrow keys to move the pixel around the screen. This will be the foundation of what can turn into a video game.

  #include 
#include 
#include 
#include 
#include 
#include 
#include 

#define COLOR_WHITE 15
#define MAX_WIDTH 320
#define MAX_HEIGHT 200

#define KEY_ESC 283
#define KEY_UP 18432
#define KEY_DOWN 20480
#define KEY_LEFT 19200
#define KEY_RIGHT 19712

using namespace std;

void set_video_mode (int mode) {
  // Create a structure for registers
  __dpmi_regs r;
 
  // Set AX to the video mode value
  r.x.ax = mode;
 
  // Call int 10 (set the video mode of the BIOS)
  __dpmi_int (0x10, & r);
}

void put_pixel (int x, int y, int c) {
  // Video VGA is at A000, so let's write to it.
  _farpokeb (_dos_ds, 0xA0000 + y * 320 + x, c);
}

void clear_pixel (int x, int y) {
  // We just write pixel 0 to clear the point
  _farpokeb (_dos_ds, 0xA0000 + y * 320 + x, 0);
}

int get_key () {
  // Create a structure for registers
  __dpmi_regs r;
  // Assign AH to 00h to call BIOS
  r.x.ax = 0x0000;
  // Invoke int 16 (BIOS keyboard handler)
  __dpmi_int (0x16, & r);
  // Return the value of AX (full scan-code)
  return r.x.ax;
}

int main () {

  // Set the video mode to 13h (320x200x256)
  set_video_mode (0x13);

  // Main loop
  int running = 1;
  int curkey;
  // Start with the middle of the screen
  int char_x = MAX_WIDTH / 2;
  int char_y = MAX_WIDTH / 2;
  while (running) {
    // If the key is pressed
    curkey = get_key ();
    // Whatever happens, we still need to clean up the pixel
    clear_pixel (char_x, char_y);
    switch (curkey) {
      case KEY_ESC:
        // Press the ESC key, so we exit
        running = 0;
        break;
      case KEY_UP:
        char_y--;
        break;
      case KEY_DOWN:
        char_y ++;
        break;
      case KEY_LEFT:
        char_x--;
        break;
      case KEY_RIGHT:
        char_x ++;
        break;
    }
    // Draw the "character" on the screen
    put_pixel (char_x, char_y, COLOR_WHITE);
  }
  
  // Go back to text mode
  set_video_mode (3);
  return 0;
}  

I hope this example gave you a basic understanding of how to handle the user input for moving the character across the screen. Some parts of the code are not perfect.

For example, to get keyboard clicks, we use INT 16. This works well, but suspends the program while it waits for input. In a more complex example, we would use INT 16 AH = 01 to check the status of the keyboard and return to the program if there is no keyboard input. This will give us time to draw other graphics. In our example, this works fine, but for a more dynamic game, you will need to write a keyboard event handler with these functions.

In addition, put_pixel and clear_pixel work well enough, but they are not as effective as creating a frame buffer and write to it. The memory buffer can be copied to any video memory at any desired speed with memcpy (). An example of its use might look something like this:

  #include 

char buffer [320x200];
int i;
 
// Change the buffer array, like any other array
 
// Periodically copy the buffer to the video memory
dosmemput (buffer, 320 * 200, 0xA0000);  

On this, we save many changes to the protected / real mode, which greatly speeds up the write operations. In addition, you can record on the screen during the selection, which allows you to perform other operations in the background – playing music, writing to disk and downloading graphics.

The best of both worlds

Even though C ++ is a high-level language, you may notice that in this example I still had to use a pseudo-assembler. This is the nature of the whole system. In the early stages of programming in DOS without BASIC, the code was often written in assembler language, and there were several standard libraries.

However, this approach has its own beauty. Instead of writing entirely in assembler, I can take advantage of the power of interrupt language calls in combination with the convenience of C ++, not to mention the powerful memory management system in protected mode, available thanks to DJGPP.

It can be said that using this system, I cheat, and if you treat this strictly, then it is. Before the advent of DOS expanders, developers had to suffer, trying to fit everything into 640 KB. And if you look realistically, they rarely even had 640 KB. On most DOS machines, after loading the drivers and TSR (resident programs), there was barely 600 KB of RAM.

This was enough for simple programs, but when more complex data structures were required, you had to use DOS expanders or EMS (extended memory ). The code could be up to 600 KB, but data spaces in complex programs and games required space for growth, and the 1 MB barrier was incredibly small. DOS expanders like CWSDPMI were real saviors!

Summing up

I hope you enjoyed our journey to the Land of Nostalgia. Programming under DOS is a very interesting area. In any other operating system, it is difficult to get close enough to the bare hardware, and without the use of DJGPP, it is difficult to achieve a balance between functionality and flexibility.

I want us to have more time for more complex examples of programs. With this development kit, our capabilities are truly limitless. We get the lightness of programming under DOS, the graphic potential of the VGA system (which, despite its ancient nature, can still create interesting game graphics) and the power of the standard C library.

Thanks to C ++, we can create a character class for the hero video games, assign variables to it (for example, the current position on the screen, health and strength) and control it using the arrow keys. Since we have up to 4 GB of addressable space (at least theoretically), we can read complex tile graphics or even whole JPG pre-rendered graphics from the disk. With the help of this system it is quite possible to create an almost modern video game.

But it will have one feature that no one today has. It can be launched on a computer that you received at Christmas at age 12.

Get down to work – your old computer is waiting for you. It's time to get to know him again.

Leave a Comment

Your email address will not be published.