2013-11-30

2013-11-30 Doom Progress Continued

So last night I cleared a few more bugs in my kernel and libraries, and got Doom to the point where it stopped outputting text to the console because it gone into its main loop ...

Loading Operating System ...
Kernel Initialised
Loading ELF library

                            DOOM Registered Startup v1.10
V_Init: allocate screens.
M_LoadDefaults: Load system defaults.
dos_openFile: Opening "devdatadefault.cfg".
Could not find the device.
Z_Init: Init zone memory allocation daemon.
W_Init: Init WADfiles.
dos_openFile: Opening "DH1:Doom/base/doom.wad".
 adding DH1:Doom/base/doom.wad
===========================================================================
                 Commercial product - do not distribute!
         Please report software piracy to the SPA: 1-800-388-PIR8
===========================================================================
M_Init: Init miscellaneous info.
R_Init: Init DOOM refresh daemon - [.....                     ]
InitTextures
InitFlats............
InitSprites
InitColormaps
R_InitData
R_InitPointToAngle
R_InitTables
R_InitPlanes
R_InitLightTables
R_InitSkyMap
R_InitTranslationsTables
P_Init: Init Playloop state.
I_Init: Setting up machine state.
D_CheckNetGame: Checking network game status.
startskill 2  deathmatch: 0  startmap: 1  startepisode: 1
player 1 of 1 (1 nodes)
S_Init: Setting up sound.
S_Init: default sfx volume 8
HU_Init: Setting up heads up display.
ST_Init: Init status bar.

My original plan was then to design and write the device management subsystem, migrate the vga driver code, implement the graphics library, then get Doom to open the graphics library in order to output to the screen.

Unfortunately (fortunately?), my impatience got the better of me and I thought I might just try a quick 'n' dirty system call to get the bitmap that Doom had generated onto the screen.  I pulled much of the code from the VGA driver that I used in the 16 colour image article, and called the initialise() function to switch from the mode 3h VGA text screen to the mode 12h VGA graphics screen, with 640x480 pixels by 16 colours.

Doom's bitmap uses 8 bits per pixel, each pixel's byte is used as an index into a colour mapping array to get a new byte, which is then used as an index into a palette array to get three bytes for red, green, and blue.  People familiar with the VGA hardware will recognise these two levels of translation as features that VGA provides natively.  I guess that's why the original Doom was written that way.  In any case, I figured I could get something recognisable if I just took the bitmap array and drew it directly, so the initial bitmap gave the value 0-255 for the blue component of each pixel.

I wrote a system call which accepted the bitmap pointer, width and height, and used a quick function to call the plot() function in the VGA driver, which gave me a quarter screen blue image, but one which bore a passing resemblance to the Doom intro screen.

This image only filled quarter of the screen, so a few tweaks had it full-screen.  Doom was designed to run a 320x200 mode 13h screen with 256 colours, so it needed enlarging.


After spending some time investigating the format of the Doom bitmap and finding out about the palette, I modified the Doom render routine.  I wanted to give the 24-bit bitmap to the system call, rather than worrying about passing it the colour map and palette.  I allocated a second screen buffer that was 3 bytes per pixel for the doom screen and added a loop to copy each pixel, translating it for the colour map and palette, and wrote the 24-bit colour to the second buffer.

I used the same bitmap drawing routine that was used for the parrot, and draw the image without dithering.  This was the first of the images that I posted yesterday.  Turned on the dithering and posted the second image.  My brain told me the image was a little "off", but I wasn't sure how.  I looked for a comparison image on Google and then spotted that red and blue were reversed.  Behold!


The vertical cyan lines are left-overs because I didn't clear the screen buffer after switching to Mode 12h, and the bitmap drawing routine supports transparency, which is why they show through the black areas.


Bugs fixed


These are the bugs I fixed in order to get Doom to its main loop.  We don't need to go into details ...

  • strncasecmp() was checking one more character than it should have been, so it couldn't find "SW1BRCOM".
  • I had stripped all of the netcode from Doom because I don't have my network stack in this kernel yet, but apparently some of it's required, so I had to put some of it back in.
  • I hadn't implemented the precision parameter of sprintf() so it didn't construct the font texture names correctly.  It was looking for "STCFN33" rather than "STCFN033".
  • sprintf() also wasn't writing a null-terminator, which apparently it needs (who knew?), so it was looking for "STTNUM10" rather than "STTNUM1".

Next Steps

When I next get time on this, I plan to address the following:

  • "Demo is for a different version of the game".  This well-known Doom error is causing the game to exit shortly after it starts.  If I can fix this, Doom should go into playing its opening demo.
  • Keyboard input.  I haven't looked into how Doom accesses the keyboard, but it will need at least key-up and key-down events which is more than the C library provides.  I'll need to think about this some more, but I'll probably create some form of message queue and port which Doom can open and listen for events.  This will be akin to how it will work under a window manager anyway.
  • Implement access().  Doom uses the access() function to determine which wad files it has available.  If I finish the implementation of this, I could upload an archive of the emulator and the game (without the wad file, maybe with a shareware wad), for people to toy with.
  • Write the device manager.  Not specifically for Doom, but the full implementation of the vga driver needs the device manager.
  • Write the proper vga driver (not the hacky one that's there now)
  • Write a sound library.  This'll probably need the device manager, and is the one big thing I don't have a pre-existing kernel for testing.
  • Make it faster!  It's not fast, we need to go faster, more speed!

No comments:

Post a Comment