Author
Topic: Experiments with C in DOS (Read 1180 times)

I've recently adopted the C language after being D-O-N-E with Java. I can only take so much ass backwardness until my head explodes.

Programming is more of a hobby for me, so my progress is often slow, but I thought I could show what I have been doing.

My machine of choice to program was my 486-DX4-100 machine, which is perfect for this sort of thing, but for portability (physically not technologically, the idea of porting this has left my mind long ago) I have installed Windows 98SE on a Prescott-era Toshiba Satellite laptop, which was a bit new for it, but it worked out.

My IDE of choice is Borland Turbo-C because of it's free status, and helpful compiler-specific features like dedicated pseudo-variables for accessing CPU registers.

Now I do plan to do more modern stuff, and I did a bit of a crash course in SDL2 which I plan to pick up, but I want to have some fun while I get used to C.

So what have I done? Something quite simple and if you have DOSBox you can try it yourself. It's a test to see if I can write text to screen memory using a pointer.

To try this out, you're going to need Turbo C, which is available for free (it's in the public domain) from a quick google search of Archive.org.Load the file as a .C and compile it without any strings attached. You may even be able to just type it in using the website based DOSBox and compile it there.

I would include an executable, but the issue is that it's currently on my 486, and I'd have to get that, and I am too American to be bothered with that tbh. If people really want I'll get off my arse and do it.

Here's a couple screenshots of what it does instead:

Now as you may be able to tell from the code, that's supposed to be a checkerboard pattern, but I don't have it offset right in order to do that, but I just would need to offset the characters that are stuck into the array by one to fix that.

So I hope this was at least somewhat interesting. I shall post again of my next feat. I can say I have been experimenting with graphics modes and have gotten some mild results from that.

I remember drooling over a 486 DX4-100 back in the day. If I'd had $10,000 I could have got one along with a color printer, that was my dream PC at the time. Unfortunately due to budget constraints I had a 16MHz 386sx.

Now that I think about it, must have been the DX2-66 I'm thinking of, it was top of the line at the time, nobody had heard of a Pentium yet, we all assumed the successor would be called the 80586. This would have been early 90s when the family PC was a 368sx-16 with a 40MB hard drive and a 14" VGA monitor. I remember being excited when we upgraded to 4MB of RAM a year or two later. It was still a constant challenge to free up a few extra KB of memory to get a game to run, that finally started to change with Doom which was the first one I recall playing that could use extended memory.

I used Borland Turbo C back in the day - at first on my 8MHz XT clone, and later on my 386 machine (never did own a 286). I designed a multi port IO card (I think it had 72 or 144 bits of IO) to control a model railroad - all by reverse engineering a grainy pic of a commercial product in a magazine. Only one chip on the commercial board was visible in the photo, but it was the main IO chip. Using datasheets for that chip I designed the interface side to work as an ISA bus card. I never actually built one, but I wrote the driver and test software for it using Turbo C.

Those were interesting times... my first job post University using Assembler (MASM) and Microsoft C, C++ was around in academia in the form of cfront and a commercial version of cfront from Glockenspiel came out but the pre-procesing and mangled names were not very helpful. I bought a copy of Turbo C++ in a computer store (Tandy or the like) whilst on holiday in Florida and in it's early version it was highly flaky with strange template support but it's IDE and the fact it was super quick was awesome. Microsoft introduced QuickC which I seem to remember was quite fun but I cannot remember the details.

it's worth digging out and moving out of the shed to somewhere where the environment is more electronics friendly, working pentium pro systems are worth $$$

They are? Hmm, this one is a random board I put in a Gateway 2000 tower ages ago so it's not an original system but it did work last I used it.

I wonder if there's any demand for the CPUs? I have several 200MHz Pentium Pro CPUs I rescued from decommissioned servers at work. Always thought they looked cool.

I spent around 300-400USD on my decked out Pentium Pro machine. The higher profile the board and the more complete of a package you have, the more you could probably sell it for.If I had a use for more chips, I'd be willing to buy one or to off you, but I don't have the dough to spend on random chips. They do look amazingly cool, and I need to thank you as a collector for not letting them be destroyed. They are a hunted species wanted for their high gold content.

Can anybody possible help me with dealing with interrupts in Turbo C? From what I understand you assign a vector to a interrupt which is actually a pointer to a C function of type interrupt that gets executed when that interrupt is called.

I tried to setvect from dos.h to a function I made of type interrupt, using interrupt 0x60, which is supposedly the keyboard interrupt, but it didn't execute the code inside the function. Help would be appreciated.

Alright, I got some REALLY cool stuff to show here, or at least I think it's cool.

So, to start off with, I wanted to get bitmap graphics work.

On IBM compatibles with VGA cards, there are two main bitmap VGA modes. You have mode 0x12, and mode 0x13. 0x12 is a planar mode requiring constant switching of memory banks to do anything. It's incredibly annoying to program for, and I haven't done it, or even tried. 0x13 on the other hand is a good, old, regular linear mode. It has a resolution of 320x200, and a 256 colour colour palette reassignable using 6bpc/18bpp colours. For the moment I am going to use the default palette.

Note, this is all compiled using Turbo C as mentioned before. If you want to try these out, grab DOSBox, Turbo C, and the source code. If there is demand I can release the compiled .EXEs

All code is for you to do with as you wish. This is all experimentation before I put time into creating a serious application.

So, my first test was to see if I could, on a delay, fill a screen completely with red.

FOREWARNING: I am linking pictures that take up a small amount of data. Metered users beware.

I am using the dos.h delay function, which is completely unpredictable based on what machine you use it on. I had it set to 25ms and the screen filled up instantly on my Prescott laptop, where on DOSBox it takes much longer. My calculations also show it should take around 26 minutes, but those could be wrong. Serious programming won't use this.

The program works perfectly besides that, slowly filling up the screen as you can see the linear buffer fill up "line by line". Here's a picture of it part way: https://prnt.sc/i8hx1w

So, next up I needed more than one colour. I have 256 of them! I want to see them all. This requires a slight code modification as such: https://pastebin.com/Y5bzBW8w

This just cycles what colour is being placed for each of the 256 available in the default palette. Here's another picture: https://prnt.sc/i8hxm7 Looks kinda cool, right?

Anyways, my next job is to somehow get bitmap graphics to work. Of course, the simplest file format is one of raw, unorganized data, and that's what I'm using. I have 256 colours, 0x00 to 0xFF, but in plain DOS I have no way to make an image like that without a third party program, or first...

This program uses a very long 1D array that is formatted like a 2D array, in which I have manually (yes, manually) placed each colour in a grid increasing. Here's the code: https://pastebin.com/USxmP4rX

This program writes that array to a file, and then reads it back and displays the data onscreen for confirmation. Here's an image: https://prnt.sc/i8hxy2

This program can display that image generated (or any image if you change the array around) at the top left of the screen as such: https://prnt.sc/i8hy9k

Perfect, but making an image in that array is tedious and difficult. While I could write myself a fancy image editor, the GIMP is already there for me, and can output in this exact raw data format, so long as I give it the right palette. Image: https://prnt.sc/i8hz9a

With graphic made, it's just a case of renaming it IMGOUT.VGA (just a random extension), plopping it in the root directory, and re-running the program: https://prnt.sc/i8hz3u

Now, this is not all I have done. My current project is to clone one of my favourite puzzle games, Puyo Puyo. (Dosso Dosso anyone?) I need some stuff for this. Modern games are run on game loops dependent on a timer. This is possible on DOS too, with either the RTC, or what I've been experimenting with, the PIT (Programmable Interval Timer). Now, this thing is annoying and complicated to deal with, and while I got a working interrupt loop, uh, working, I couldn't seem to adjust the time used, so I am going to look at the RTC, and see if that works any better for me (like a coward).

I'm going to no longer post pictures here, as there is not much of a need to, and I am too lazy to compile the rest. I will, however, explain what I've done here. All this program does is program the PIT to run at a clock rate (changing the values sent do nothing, so I am likely doing something wrong here, any help?) and then install an interrupt handler at vector 0x08 (IRQ0). This then counts up a number and displays it to screen. This works perfectly.

One last thing, keyboard input. This is easy enough, the BIOS stores keyboard input into a buffer, and it can be read out using BIOS interrupt 0x16. Here it is: https://pastebin.com/YkHW1aBd

This, on a delay of 100ms, or it's supposed to be, just reads the keyboard buffer, prints it to screen, and then halts if it reads a lowercase k. Works perfectly.

So, this is my progress so far. Sorries for the long post, I just have a lot of stuff to show. Right now, I have to figure out a more reliable timer. wiki.OSDev.org has been a major resource for me, and it claims a better reliability with the RTC, so that's something for me to look into. I also need to ask a quick question. How do I figure out where the executable is on the drive so I can access files that are in the same directory?

Anyways, thanks for reading this far. I hope my petty victories aren't too boring, but I've had a lot of fun.

Hmmm, code doesn’t seem to run under FreeDOS, though it should. Interesting. Might be a bug with JEMMEX, let me see if I can track it down.

Also, just curious: What drove your choice of TurboC, compared to something current like OpenWatcom? Having an IDE is nice I suppose, though I prefer to write the actual code in a modern editor and either cross compile or compile in a DOS VM (For all my FreeDOS kernel development work I edit in Atom on my MacBook; the source tree sits in a VMware shared folder (mounted via vmsmount) so all I have to do is switch to the FreeDOS VM and type “build”; it’s a nice system and I really like it. You could do the same with DOSbox as well.)

There are a couple reasons for Turbo C. Probably the main one I guess is the low-level friendly additions Turbo C makes, like the register pseudos like _AH, _AL, _AX, etc. I do actually use a modern editor for Turbo C on most occasions. I write all my code in Notepad++ and then save it to a folder in DOSBox, then just run it in Turbo C. The other reason is just because I heard of it. It was probably the first thing I found, or already saw for a DOS C compiler.

You have to use Turbo C to compile this, because of the register pseudos, as they do not work in any other compilers that I know of (maybe TC++). There's no real reason it shouldn't work in FreeDOS, as it can almost run without DOS. The only thing it really uses from DOS are some delay functions, which could be replaced with either nothing, or the PIT.