Thursday, July 20, 2017

The FAST and SOFA compilers

As part of the FreeDOS Summer Coding Blog Challenge, Bruce Axtens writes on his blog about the history of the FAST and SOFA compilers for FreeDOS.

If you don't know about FAST and SOFA, FAST is loosely based on Basic, Pascal, C and Assembler. The programs produced by FAST are very small and very fast. SOFA is an 8088 (and semi-80386) assembler, with syntax based somewhat on A86 and CHASM.

Both FAST and SOFA were created by Peter Campbell, who passed away in 2007. FAST and SOFA have since been released under the GNU GPL.

Thursday, July 6, 2017

How to compile bwBASIC from source

Dr Owain Kenway recently wrote about a problem he discovered with Bywater BASIC, one of the BASIC interpreters we include in the FreeDOS 1.2 distribution. Looks like we made a mistake on our end by including the Win32 version, but Owain shows how to recompile a native DOS version. You can read his how-to on his blog:

Fixing bwBASIC on FreeDOS »

While this isn't necessarily part of the FreeDOS Summer Coding Blog Challenge, I'd like to include it as such because it shows the power of open source software: you can always compile it yourself.

(We'll also update the bwBASIC package on our end. Thanks, Owain!)

Wednesday, July 5, 2017

How to support different spoken languages in FreeDOS programs

All summer, we are doing the FreeDOS Summer Coding Blog Challenge, where we ask you to write and share some tips that new developers can use to get started in FreeDOS. I thought I'd start by writing about the Cats and Kitten libraries to support different spoken languages in your programs.
When you write a new program, you probably don't think about spoken languages other than your own. I am a native English speaker, so when I write a new program, all of my error messages and outputted text is in English. And that works well for the many people who have English as their native language, or who know enough English as a second language to get by. But what about others who don't speak English, or who only know a little English? They can't understand what my programs are saying.

So in the early 2000s, I decided FreeDOS should have a system to support different spoken languages. This type of multi-language support is called Internationalization (or "I18N," because there are eighteen letters between the "I" and "N").

I looked around at how other popular systems had implemented multiple spoken languages. The standard Unix method is with a set of C library functions built around language "catalogs." A catalog is just a file that contains all the error messages and other printed text from a program. In the Unix method, you have a different catalog for every language: English, German, Italian, Spanish, French, and so on.

My first FreeDOS I18N library was a stripped-down implementation of the Unix method. This is a very simple method. Every time you want to print some text in the user's preferred language, you first look up the message string from the catalog using the catgets() function—so named because it will get a string from a message catalog.

In Unix, you use catgets() this way:

  string = catgets(cat, set, num, "Hello world");

This fetches message string number num from message set set, from language catalog cat. The organization of messages into sets allows developers to group status messages into one set (say, set 1), error messages into another set (such as set 7), and so on.

Before calling catgets(), you need to open the appropriate language catalog with a previous call to catopen(). Typically, you have one catalog per language, so you have a different language file for English, another for Spanish, etc. Before your program exits, you close any message catalogs with calls to catclose().

If the string doesn't exist in the message catalog, catgets() returns a default string that you passed to it; in this case, the default string was "Hello world."

I implemented a simplified version of these functions in a FreeDOS Internationalization library called Cats. To save on memory, Cats supported only one open catalog at a time. If you tried to open a second message catalog, the call to catopen() would return an error (-1).

Message catalogs were very simple under Cats. Implemented as plain text files, Cats loaded the entire message catalog into memory at run-time. In this way, you didn't need to recompile the program just to support other languages; you just added another message catalog file for the new language. An English message catalog for a simple program might look like this:

  1.1:Hello world
  7.4:Failure writing to drive A:

The same message catalog in Spanish might look like this:

  1.1:Hola mundo
  7.4:Fallo al escribir en la unidad A:

For example, the string "Failure writing to drive A:" is message number 4 in set 7.

The Cats library was a simple way for developers to add support for different languages in their programs, written in C. And because Cats implemented a Unix standard, it made porting Unix tools to FreeDOS much easier. Once you added the calls to catgets(), all you needed to support other languages was a message catalog that someone translated to a different language. And I kept the Cats message catalogs very simple; they were plain text files.

Cats was a neat innovation, but loading the messages into memory was cumbersome because it used streams. I admit that I just did it the quick and easy way. Fortunately, other FreeDOS developers improved on Cats to optimize the loading of catalogs, reduce memory footprint, and add other enhancements. The new library was noticeably smaller, so we renamed it Kitten, also written in C.

Because of the optimizations, Kitten used a slightly different way to retrieve messages. Since Cats only supported one message catalog at a time anyway, Kitten removed the cat catalog identifier. Once you open a message catalog with kittenopen(), all calls to kittengets() assume that message catalog. You only need to make a single call to kittenclose() before you end the program.

Using Kitten made it much easier to support different spoken languages in FreeDOS programs. Here's a trivial example to put it all together:

  /* test.c */

  #include <stdio.h>
  #include <stdlib.h>
  #include "kitten.h"

  int
  main(void)
  {
    char *s;
 
    kittenopen("test");
 
    s = kittengets(7, 4, "Failure writing to drive A:");
    puts(s);
 
    kittenclose();
    exit(0);
  }

This loads a message catalog "test" into memory, then retrieves message 4 from set 7 into a string pointer s. If message 4 in set 7 isn't found, kittengets() returns the default string "Failure writing to drive A:" into s. The program prints the message to the user, then closes the message catalog before exiting.

Typically, you name the message catalog after the program's name. So the message catalog for the FreeDOS CHOICE program is "choice". Kitten searches for the language file in a few locations on disk, and always appends the value of the %LANG% environment variable, which is typically set to the two-letter language abbreviation: "en" for English or "es" for Spanish. The DOS filename for the English version of the "choice" language catalog is CHOICE.EN, and the Spanish language version is CHOICE.ES.

A limitation to Cats and Kitten is that it can only support single-byte character sets supported by DOS. So Cats and Kitten cannot support Chinese or Japanese, but should do fine with most other languages.
You can find Cats and Kitten at the FreeDOS files archive on ibiblio, under devel/libs/cats/

We made three revisions to Kitten, so the latest version is Kitten revision C, which you can download directly as kitten-c.zip.

FreeDOS contributor Mateusz "Fox" Viste wrote a similar implementation for Pascal programs, called Cubs. You can also find it on ibiblio, under devel/libs/cats/cubs/

FreeDOS developer Eric Auer created a command-line version of Kitten, named Localize, so you can provide internationalization support for DOS Batch (BAT) files. Find it on ibiblio, under devel/libs/cats/localize/

Monday, July 3, 2017

FreeDOS Summer Coding Blog Challenge

FreeDOS just celebrated our 23rd birthday on June 29. That's a long time for any open source software project, so while there wasn't anything special about "23," we decided to mark our project's anniversary with a FreeDOS Blog Challenge. For the blog challenge, we asked you to share your "FreeDOS story" about how you discovered FreeDOS or how you used FreeDOS. During the month of June, we shared these FreeDOS stories as "guest posts" on our blog. Thanks to everyone who sent in a story! You can find links to all the stories at "Happy 23rd birthday to FreeDOS!"

Since the blog challenge was such fun, a community member on Facebook suggested a followup. I thought that was a great idea.

Announcing the FreeDOS Summer Coding Blog Challenge! Throughout the summer, share your tips about programming for FreeDOS. Post them on your own blog, or email them to us and we'll do guest posts for you.

What should I write about?
You might write a "how-to" article about how to manage very large arrays in memory, or how to load very large files. Or maybe you could talk about how to optimize a DOS program's I/O operations, such as how to read chunks of a file into a memory buffer using read() rather than using streams. Or you might want to write an article about how to use the conio functions to control the screen and read from the keyboard. Or maybe you could write something a little more "entry level" like tips to use the FreeDOS Kitten library to support multiple languages in your program.

Your "how-to" articles don't necessarily need to be about coding in a language like C or Assembly. If your preferred programming language is Pascal or BASIC, then write something about how to write programs in those languages for FreeDOS. If it's a programming language that's included in FreeDOS, we'd like to include it in the FreeDOS summer coding challenge.

Don't limit yourself to compiled languages, either. You can do lots of clever things at the FreeDOS command line and in BAT ("batch") files. So you could write an article about how to use a batch menu tool, like Jerome's V8 PowerTools included in FreeDOS 1.2, to create a neat interactive "program" as one smart batch file.

We want to hear from everyone! It's not just about developers, or people who contribute to the FreeDOS Project directly. The FreeDOS summer coding challenge is for anyone.
How do I write an article?
If you don't often write for a blog, then writing a FreeDOS "how-to" article might seem a little daunting. But really, it's easy!

I recommend you write your article as though you were explaining it to a friend. If it helps, write a draft in your email program, so you can convince yourself you're emailing someone about programming in FreeDOS. And if you like, you can actually send that email message to me (jhall@freedos…) and I'll use it as a guest post on the FreeDOS blog.

If you have your own blog or website, post your story on your blog, and email me to let me know where to find your article. If you don't have your own blog, I would be happy to post it for you as a "guest post" here. I'll even do light editing for you and take care of formatting.

Don't worry about making it perfect. I can do light editing for you before I put it up as a guest post. As in the FreeDOS Blog Challenge, I'll edit for spelling, grammar, and style before I post your article on our blog. I try not to make changes to content or to the flow of your article—but if I do, I'll always run the changes by you first.
Send us your story by September 30!

If the FreeDOS summer coding challenge works out well, we might do a similar blog challenge in winter, maybe about your favorite DOS applications.

Guest post: Updating BIOS with FreeDOS

Lars Noodén shared this note about using FreeDOS to update the BIOS on a computer. On the FreeDOS website, we like to say that most people install FreeDOS to play classic games, run legacy software, or do embedded development. And for installing FreeDOS, that probably covers almost everyone. But there are a lot of folks who use FreeDOS to do exactly what Lars describes: update the BIOS.

I use FreeDOS only occasionally—but when I have used FreeDOS, it has been a life saver. The most recent time was when I needed to update the BIOS on an old laptop. I was able to make a FreeDOS image containing the BIOS update and then modify GRUB2's configurations to allow me to boot it. The GRUB2 part, as opposed to GRUB1, was hard. The FreeDOS part was straightforward and easy. Here's how I did it:

This was all done on an ancient laptop using a Long Term Support (LTS) version of Ubuntu GNU/Linux for AMD64 computers, which to my consternation used GRUB2.

First, after downloading the FreeDOS boot floppy and unzipping it, I mounted the resulting disk image read-write using the "loopback" device so that I could edit it. I copied the vendor's ".EXE" style BIOS update there so it would be available while FreeDOS was running. I then removed AUTOEXEC.BAT so that I would get the normal command prompt when booting. Then I unmounted the disk image and it was ready to go, so I copied it to /boot/floppy.img and was all set with that. That was the easy part.

Next was the hard part with GRUB2. While it was fairly easy to figure out how to configure the old GRUB1, the new version is not. After much searching online, I ended up "cargo-culting" it. So if you follow this route, try to find and read current documentation. It turned out that I had to first to get memdisk into the /boot directory. The package syslinux at the time could do that—although now the package grub-imageboot seems to do that job, and installing it puts memdisk directly in /boot for you.

Then GRUB2 had to be configured to offer memdisk and the modified FreeDOS boot floppy as an option. That is done by creating a new file, /etc/grub.d/42_custom, and making it executable. In it, I put the following:
 #!/bin/sh
 cat <<EOT
   menuentry "FreeDOS" {
     linux16 /boot/memdisk
     initrd16 /boot/floppy.img
   }
 EOT
Then once update-grub was run, FreeDOS showed up in the boot menu starting with the next boot.

And with FreeDOS now in the boot menu, it was just to reboot the computer, select FreeDOS, and then run the BIOS update from the A: prompt. After the BIOS update ran to completion and I was back in Ubuntu, I removed the GRUB2 entry.

FreeDOS really saved the day in that way, since there was no other way to conjure the equivalent of a bootable floppy disk.

-Lars Noodén