Experiments with C in DOS - Page 1
Forum section: electronics / general

author: Ampera
author_rank: Super Contributor
timestamp: January 10, 2018, 05:47:52 am
content: 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.Here's the code in pastebin form:https://pastebin.com/aKWgfjPLTo 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.

author: james_s
author_rank: Super Contributor
timestamp: January 10, 2018, 06:15:46 am
content: 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.

author: paulca
author_rank: Super Contributor
timestamp: January 10, 2018, 11:49:46 am
content: Reminds me of doing things like:POKE 20, 20On the Spectrum which either* did nothing* locked up* reset* Made pretty wall paper - write that one down.

author: Ampera
author_rank: Super Contributor
timestamp: January 10, 2018, 04:56:03 pm
content: Ah, BASIC POKEing. That's always fun (not)Also if you think a DX4 is nuts, I also have a 200mhz Pentium Pro with a Mach64/GX, Voodoo 1, 128MB RAM, SB32 (CT:3670), and some other neet stuff.

author: james_s
author_rank: Super Contributor
timestamp: January 10, 2018, 06:03:24 pm
content: I have a Pentium Pro somewhere too, I think it's in the shed at my mom's house. That was a long way off from being developed when I was drooling over 486's.

author: Ampera
author_rank: Super Contributor
timestamp: January 10, 2018, 06:40:38 pm
content: i486-DX4 came out in 1994, PPro was 1995 so I don't believe that far off. Not to mention Pentiums that could already thrash the 486 Like the Socket 5 P100s were already out at around the same time.

author: paulca
author_rank: Super Contributor
timestamp: January 10, 2018, 07:12:48 pm
content: About 10 years ago I had a Pentium running as a network firewall. Took me ages trying to cross compile linux on an i686 machine for i586.It ran great. The old 2Gb SCSI disc in it failed one day, I heard it clack, spin down and stop. However I could still log into it and the disc was dead. Lots of kernel errors about it.I just left it on for another year and it worked fine as my firewall with no discs at all.Valiant little beast. Eventually though there was a power outage and... no more firewall. Never rebooted, went to the dump.

author: james_s
author_rank: Super Contributor
timestamp: January 10, 2018, 07:15:41 pm
content: 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.

author: free_electron
author_rank: Super Contributor
timestamp: January 10, 2018, 07:40:43 pm
content: my first pc was a 386DX -25 .. none of that crippled SX stuff !

author: rrinker
author_rank: Super Contributor
timestamp: January 10, 2018, 08:18:12 pm
content: 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.

author: Ampera
author_rank: Super Contributor
timestamp: January 10, 2018, 08:42:04 pm
content: Turbo C has actually been a pleasure for me to work with. I am really enjoying it.

author: james_s
author_rank: Super Contributor
timestamp: January 10, 2018, 10:39:31 pm
content: Quote from: free_electron on January 10, 2018, 07:40:43 pmWould have been nice, but my family couldn't afford such a luxury. Until the 386sx we were getting by with an original IBM PC with 512k and a CGA monitor, the 386 was a huge upgrade.

author: dexters_lab
author_rank: Unknown
timestamp: January 11, 2018, 09:10:56 am
content: Quote from: james_s on January 10, 2018, 06:03:24 pmit'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 $$$

author: timb
author_rank: Super Contributor
timestamp: January 11, 2018, 10:24:55 am
content: Quote from: TwoOfFive on January 10, 2018, 08:42:04 pmThe Turbo C++ compiler has some efficiency and performance gains, so you might want to grab a copy. (WinWorld.com has a it.)(Turbo C++ was a direct continuation of Turbo C.)

author: NivagSwerdna
author_rank: Super Contributor
timestamp: January 11, 2018, 11:03:07 am
content: This thread brings back a few reminiscences...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.Fun times.Now back to the Java...

author: Circlotron
author_rank: Super Contributor
timestamp: January 11, 2018, 12:17:56 pm
content: Quote from: james_s on January 10, 2018, 07:15:41 pmAt the time the word on the street was that you could copyright a name but you couldn't copyright a number, so '586 got called Pentium by Intel.

author: Frank
author_rank: Contributor
timestamp: January 11, 2018, 12:51:11 pm
content: Good times with DOS...Try to program some "Terminate and Stay Resident" (TSR) programs! You can try to make some clone of an early DOS virus

author: james_s
author_rank: Super Contributor
timestamp: January 11, 2018, 06:57:31 pm
content: Quote from: dexters_lab on January 11, 2018, 09:10:56 amThey 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.

author: Ampera
author_rank: Super Contributor
timestamp: January 11, 2018, 07:02:28 pm
content: Quote from: james_s on January 11, 2018, 06:57:31 pmI 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.

author: dexters_lab
author_rank: Unknown
timestamp: January 11, 2018, 09:57:29 pm
content: Quote from: james_s on January 11, 2018, 06:57:31 pmvery much so, the pentium pro is the holy grail for gold recovery which is one of the reasons they are so hard to get (without paying OTT for them)

author: Ampera
author_rank: Super Contributor
timestamp: January 12, 2018, 06:39:17 am
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.

author: helius
author_rank: Super Contributor
timestamp: January 12, 2018, 11:55:17 am
content: Did you find the Turbo C user manual athttp://bitsavers.informatik.uni-stuttgart.de/pdf/borland/turbo_c/Turbo_C_Users_Guide_1987.pdf? There's also a corresponding reference book. ISRs are covered on pp 281-284. Just follow the examples.

author: Ampera
author_rank: Super Contributor
timestamp: February 01, 2018, 06:24:04 am
content: 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 .EXEsAll 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.First off, here is the code:https://pastebin.com/cS2wXkSuI 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/i8hx1wSo, 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/Y5bzBW8wThis just cycles what colour is being placed for each of the 256 available in the default palette. Here's another picture:https://prnt.sc/i8hxm7Looks 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/USxmP4rXThis 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/i8hxy2Sweet! I, however, do now need a program to display this. Here is that program:https://pastebin.com/at2Kcz7xThis 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/i8hy9kPerfect, 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/i8hz9aWith 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/i8hz3uNow, 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).Anyways, here is the code I wrote:https://pastebin.com/bZ7zNV0LI'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/YkHW1aBdThis, 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.

author: timb
author_rank: Super Contributor
timestamp: February 01, 2018, 09:01:46 am
content: 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.)

author: Ampera
author_rank: Super Contributor
timestamp: February 01, 2018, 02:24:07 pm
content: 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.

author: timb
author_rank: Super Contributor
timestamp: February 01, 2018, 11:11:55 pm
content: Quote from: TwoOfFive on February 01, 2018, 02:24:07 pmWhich version of TC did you use? There are some small, intrinsic differences between TC 2.0, TC 3.0, TC++ 1.01, Etc., though your code should compile and run fine in any of them. (TC++ is just a newer version of TC; they just added C++ support to the compiler.)Actually, all of the popular DOS C compilers allow you to do inline ASM, directly access registers from C code, call interrupts and so on.Manipulating registers from C code should be as easy as just calling “r->ax = whatever”. That should work with pretty much every compiler (TC, TC++, Borland C, Microsoft C and Watcom C).Take the FreeDOS kernel for example. It’s written in a mix of C and ASM and will compile in any of above mentioned compilers (however the pure ASM Code is sprinkled with #ifdef statements adding and removing bits on a per compiler basis; that said, the high level C code is pretty clean).I guess what I’m saying is the C/CPP compilers for DOS were pretty compatible. It’s the ASM products you have to watch out for. (TASM and MASM with all their modes!)Anyway, I’ll try again with TC. Might be something with my patched version of TCPP.

author: Ampera
author_rank: Super Contributor
timestamp: February 01, 2018, 11:35:04 pm
content: TC 3.0 afaik doesn't exist. I am using the final version of Turbo C (I think 2.01I'm aware there's other stuff, and possibly even better stuff. I'm not entirely sure how I stumbled across this, but I've gotten used to it. For the same reason I use Netbeans for modern C programming, I've just gotten used to it.This is all for entertainment purposes anyways. If I was serious about DOS programming, I would drop C and go with Assembly, as it's the somewhat more efficient option.

author: timb
author_rank: Super Contributor
timestamp: February 02, 2018, 12:53:34 am
content: Quote from: TwoOfFive on February 01, 2018, 11:35:04 pmSorry, I meant TCPP 3.0. It went like this: TC1.x, TC2.x, TCPP1.x, TCPP3.x. (They skipped TCPP2.x.)TCPP is 99% backwards compatible with TC, but produces much more optimized binaries (in both speed and size), so it’s well worth upgrading IMHO.As for assembly and efficiency, unless you’re writing an OS kernel or something that touches the bare metal, a modern C compiler (like OpenWatcom) will generate highly efficient binaries. More so than you could do in assembly. You can also do inline ASM in your C program for the times you really need the extra performance.DOS C programming is a lot like modern embedded programming, which is why I like it. (Compared to Windows and MSVCPP, where you need dozens of libraries and several hundred MB of runtimes installed just run a Hello World program.)

author: Rick Law
author_rank: Super Contributor
timestamp: May 11, 2018, 05:41:04 am
content: Microsoft C v6 which was a repackage of Green Leaf C was rather good.I started with Demest C with soft ICE for debugging, then Greenleaf, then MS C. The debugger with the last DOS version (for MS C or Greenleaf C, which was identical) was great for that time. I tried Turbo C's briefly, but ran back to MS C V6 for the capabilities it offered.

author: Ampera
author_rank: Super Contributor
timestamp: May 11, 2018, 10:28:23 am
content: Quote from: Rick Law on May 11, 2018, 05:41:04 amI've currently moved to Turbo C++ after some weird compilation issues that I had with Turbo C, but I'm pretty much wrapping up my time with DOS for now. It's a fun hobby, but whatever I make I end up hitting a road block, and my mind isn't fully assembly ready, which is what I believe I would need in order to make any effective use of standard DOS. Watcom C was strange to me, and something I didn't touch much, despite it's native DOS extenders. I would honestly rather program all that myself, when and if I wish to do that. For now, I'm working on using C11 and the SDL2 libraries to make my programs. I will be coming back to DOS every so often, though.

author: rdl
author_rank: Super Contributor
timestamp: May 12, 2018, 06:50:03 pm
content: I bought a copy of Borland Turbo C++ back in the mid nineties, but never had time to spend on it. Best I remember it was for Windows 3.1, and I'm pretty sure I still have all the manuals and floppy disks somewhere.

author: Ampera
author_rank: Super Contributor
timestamp: May 13, 2018, 03:29:28 am
content: That's neat. Indeed some versions of TC++ had Win16 support.I believe I'm actually using Borland C++, not Turbo C++, as BC++ has some nicer features than TC++. Regardless, I'm moving my efforts towards other areas.

author: rhb
author_rank: Super Contributor
timestamp: May 13, 2018, 12:41:15 pm
content: There is a *very* serious downside to C on a DOS machine. If you have a pointer error you may be forced to reformat the disk and reinstall.I had that happen one time and never tried programming on DOS again. I stuck to Unix like God intended.

author: helius
author_rank: Super Contributor
timestamp: May 13, 2018, 09:45:06 pm
content: That sounds pretty far-fetched. What an absence of permissions means on DOS is that you shouldn't run unverified batch scripts. The chance of a "pointer error" (like reading past the end of an array or something) actually writing garbage on to the disk is pretty minimal. It's not like the disk contents are memory mapped (as they can be in Unix!)

author: Ampera
author_rank: Super Contributor
timestamp: May 13, 2018, 10:31:25 pm
content: That's what I thought. The program is loaded into memory, and unless you use disk I/O functions, it shouldn't do any of that.

author: Ian.M
author_rank: Super Contributor
timestamp: May 13, 2018, 11:01:00 pm
content: It was *possible* back when MFM and RLL hard drives were the thing for rogue code using function pointers to cause a jump to the entry point in the hard drive controller card's ROM for its low level format routine, but even back then it was very unlikely. Its also possible to do nasty things to system files if you are coding low level disk access routines. However if you are doing that sort of coding under DOS and not using a VM, you should probably use a test machine that's separate from your development machine, with nothing important on its hard drive. Restoring MSDOS + MS NET (for ease of data transfer from your development machine) from a bootable USB stick or CDRW doesn't take very long and can easily be automated.

author: alank2
author_rank: Super Contributor
timestamp: May 13, 2018, 11:05:29 pm
content: Quote from: helius on May 13, 2018, 09:45:06 pmI did a lot of DOS development in a DOS environment for years. I fully knew that doing anything wrong in C can and will quickly lockup a system quickly, corrupt memory, etc. Yes, it is possible that an out of control buggy program might accidentally corrupt the file system by calling a disk write to the wrong place by mistake. I never had that happen [in many years of risking it!], though I knew it was possible and always had a backup of my system in case it did.With all that said, I was pretty pleased to move to Windows NT 3.51 with its virtual dos machine. No worry of it corrupting what it doesn't have access to! I remember that NT window popping up very often telling me it was trying to execute an illegal instruction (when I did something wrong with a pointer usually!!!!).

author: netdudeuk
author_rank: Frequent Contributor
timestamp: May 26, 2018, 05:38:21 pm
content: I started programming the PC (a Tandon 286) in 1989 / 1990. I used the Microsoft C compiler and assembler to produce a graphical application which needed a VGA card, which was quite good for the time.I had an extra monochrome (MDA) graphics card and monitor, which allowed me to run the CodeView debugger and see the graphics at the same time.I could single step right through the C and assembly language on the mono display and watch the graphics application on the colour display.Breakpoints, register display, etc, etc made it a great development environment for the time.