2013-11-02

2013-11-02 Doom!

I don't know if I mentioned, but a while ago I downloaded the source code to the Linux port of Doom with the intention of getting it working with my OS.

"Why Doom?" I hear you ask.

  • Doom is a complex C program with proven functionality.  While I'm making Doom work with my OS, it's going to require me to write a lot more of the basic kernel and C library functionality.  Also the code should work so if there's a problem, it's probably in my code.
  • Doom is well known.  When I mention to people that I'm writing an OS, I commonly get asked "Does it run World of Warcraft / Counter-Strike / Half-life 3 etc.?"  I like to think that they're trying to get an idea of the capabilities of my OS in terms that they understand, so by being able to say that it'll run Doom, they'll get exactly that.
  • Doom has modest system requirements.  Given that my test systems have at most maybe 128Mb and maybe a 1GHz processor, Doom should run nicely, even with the inevitable inefficiencies of my code.
  • Doom doesn't require multiple threads.  Doom is intended to run on a DOS like system, so has no inbuilt dependency on the operating system to provide multi-threading support.
  • Doom has modest graphical requirements.  Given that my OS is firmly seated in the world of 640x480x4 (16 colours) for now, having a program which doesn't need many colours or a large screen resolution is a good thing.
  • Doom is awesome.  I mean come on, it's DOOM!  (Remember when first-person shooters were called "Doom clones"?)


So all that aside, how do we do this?

Firstly, Doom has two files (i_video.c and i_sound.c) which handle ... well ... video and sound.  Given that both of these are going to need some special consideration and a lot of work to get going, we'll put these off until later, so let's strip out the content of the all the functions.  I've a lot of work before it will call any of these anyway.

It looks like Linux has two different interfaces for accessing files, the C library fopen() and fread() functions, and the open() and read() functions from fcntl.h and unistd.h.  Doom uses both of these in varying measure.  Rather than pollute my current libc with functions that don't belong there, I should probably create a libkernel to contain everything else.

... some time passes ...

Ok, so with a lot of reorganising of header files, adding a new library to the project, and writing a lot of stub functions (one of which being the scanf-type functions, that's not going to fun to write), the OctoDoom executable builds.

While I do have ELF loading code (used for the HelloWorld program), I still haven't wired it up to the file loading routines so that I can load an actual executable file (it's on my to-do list).  For now, I'll have to load the Doom executable the same why as I do the HelloWorld one, that is, using Bochs to load the binary into memory at some high address.

So the first test run of Doom wasn't very successful (when are they?).  I think that the problem might be that I'm loading a program that's 987Kb into a memory that was only 1Mb to start, probably not going to have a good time.  That and the ELF loader call to kmalloc wasn't sanity checking the return value for a valid pointer.  So I had run out of memory, malloc returned NULL and the ELF loader carried on trying to use that pointer, schoolboy error.

Oh yeah, now it's loading Doom and getting as far as the main() function ... this stuff just got real!

No comments:

Post a Comment