June 3, 2012

I’m happy to announce that the source code for Aeon is now available on CodePlex. I’m not currently looking for project contributors, but if you have been interested in the project and would like to take a look, have at it.

Just a few obligatory notices:

This was developed over several years, and survived several of my changing coding styles, so its structure and design is a bit of a mess

The currently released version is older; I’ve made some compatibility changes, code refactoring, and performance tweaks so I’ll have a new official build released soon

February 25, 2012

Programming is kind of an odd hobby, since it’s also what I do for my day job. I created Aeon (and before it, other projects) as a kind of outlet for solving challenging development problems. Since it’s all mine and just for fun, I don’t really have to stick to any established design patterns or coding standards. I don’t even have to design around the requirements, because I’m constantly making those up as I go. Because of this, it’s not what I would call a shining example of cleanly architected code, and I’ve been investing some effort lately into restructuring things in the hope that it will make things easier going forward.

The biggest challenge I’m facing now is trying to extricate my DOS implementation from everything else, so that (in theory) Aeon could be run without it – say to install MS-DOS or some other variant and use it more as a true virtual machine. I actually started reimplementing my DOS code from scratch, and spent quite a few weeks on this. I had grand plans of a clean, maintainable, and accurate simulation of MS-DOS.

Sadly, it wasn’t meant to be. As the time went by and I was adding interface after interface, I ended up with an object model that turned by current tightly-coupled DOS into a loosely-coupled mess that was orders of magnitude worse.

Sometimes It’s Tightly Coupled for a Reason

MS-DOS was a complicated mess of features in the unfortunate position of becoming a de facto standard. Since it was a standard, tons of programs built for it actually relied on some if its more quirky behavior, so it could never really be improved architecturally. My mistake was thinking that by just adding some abstraction, I could elegantly implement DOS. Sometimes a cigar is just a cigar, and sometimes a mess of contradictory requirements is just a mess of contradictory requirements.

My solution to the DOS problem was to greatly increase the complication by adding level upon level of logic to abstract it away and hide it. Of course, since I was the one writing these abstraction layers I was just making more work for myself. My goal now is just to minimize and isolate. Of all of the ridiculous changes I made trying to reinvent the wheel, I’ve only actually ended up keeping a small number of trivial classes. Lesson learned. Again.

February 23, 2012

Despite the lack of updates to this blog, I have actually been working on Aeon. I haven’t been working on it nearly as much as I have in the past. Between my day job and my other obligations it’s sometimes been a challenge to find time to keep going.

That being said, my tentative plan for Aeon this year is to refactor portions of the code that have become very difficult to maintain, and to improve MS-DOS compatibility in the process. I’ll be writing up another blog post about that soon (for reals this time). The short version is that I ended up undoing a lot of the “improvements” I was making when I realized how vastly overcomplicated my new design was :)

Of course, refactoring isn’t that great of a feature since it doesn’t add features or fix any bugs, but it will give me enough confidence about the codebase that I can start to consider making it available for download. So far, I just haven’t wanted to deal with the extra hassle of (and sometimes drama) that goes along with making a large project like this open-source (not to mention the fact that another project very nicely fills this void already), but I’m not working on it as much as I used to, so maybe that will happen later this year.

July 26, 2011

Writing something like Aeon meant that I’d often find myself poring over disassembly instructions from some old, clever code. By clever, I mean performance optimizations which seem especially exotic (or just nonsensical) today. Not that we don’t have our own exotic optimizations today, but most of the ones I run into are in old games – and games rarely concern themselves with maintainability: you ship the game, maybe patch it here and there, but ultimately it’s just a piece of consumer software that will likely be discarded in at most a year or two.

Anyway, with that bit of pointless exposition out of the way, I’d like to introduce you to the HLT instruction. It takes no operands, and simply tells the CPU to halt: that is, it will just stop what it’s doing and enter a low-power state until an interrupt wakes it up. It’s employed by operating systems today to conserve energy when the system is idle, but the intended use doesn’t really matter for this article. I was puzzled for a very long time when I came across a HLT instruction in Jazz Jackrabbit some time ago (more specifically, it was in the protected-mode extender that came with Turbo Pascal 7). I figured no DOS game would have any reason to use this instruction intended for operating systems, so I tried in vain to find an emulation bug in Aeon that would explain why a JMP instruction pointed to a HLT.

I finally fired up a debugger on a real DOS system and determined that there was no bug in Aeon. Jazz Jackrabbit was actually trying to halt the CPU. (Never thought I would write that sentence…) Actually, it was trying to halt the CPU from user mode, which according to the Intel documentation on the instruction should cause a General Protection Fault exception. This exception would then be handled in kernel mode, and in the case of Jazz Jackrabbit’s DOS extender, a handler would examine the user mode stack and take some action, then eventually return control to user mode. Basically, they had used a General Protection Fault exception to transfer control to kernel mode.

Why would anything do this? It made no sense to me, but once I implemented this behavior the game loaded up and worked just fine (well, except for the distorted sprites… bah, that’s another story)

Well, recently I’ve finally gotten a copy of Raymond Chen’s book. In it (also on his blog), he relates a story that Windows ended up spending a lot of its time handling Invalid Instruction Exceptions because at the time, causing one of those was the fastest way to switch to kernel mode. Doesn’t seem like much of a stretch that the authors of Turbo Pascal 7’s DOS extender would have used a similar technique…

June 30, 2011

Not too many changes in this release, except for a significant amount of optimization in instruction decoding. I’ve noticed the biggest impact on 64-bit systems – upwards of 40% in some applications in my informal testing, but much less substantial on 32-bit systems.

Optimized instruction decoding: emulation is much faster on x64 and a little faster on x86

Fixed CD-ROM bug where Aeon wasn’t detecting some of the content in directories with lots of files

May 1, 2011

I’ve mentioned before how I used to love point & click adventure games. The series that really stood out the most for me was Quest for Glory.

I like them, but these games are really pretty strange – part adventure game, part RPG, part parody, and they somehow managed to be both epic and farcical. Not too many games could pull off the sheer number of puns they used. That being said, they aren’t without their problems – the combat ranges from clunky at best to aggravating at worst, although due to the game design fortunately most of it could be avoided.

One of the cool things about these games was how the solutions to most of the puzzles were completely different depending on whether you played the game as a fighter, mage, or thief, and the fact that you could import your character from one game to the next, so your character stats would follow you through every game. Five Quest for Glory games were made, the first four work in Aeon, but the fifth one was made for Windows 95 – there is no DOS version. Unfortunately, it pretty much only runs on Windows 95 too, so you’d have trouble running it outside of a virtual machine or an old PC. The final game is generally considered the weakest in the series, so it’s not that big of a deal, but I still like it as a nice epilogue to the first four adventures.

If you’ve never played these before, I’d still recommend them (if you can find them): simple, goofy fun, with some really great music. I should also mention, however, that Quest for Glory II was the only game in the series to never receive an official VGA makeover – instead, some very dedicated and talented fans created one a few years ago. They made a huge number of improvements over the original, but kept all the charm – and you can download it for free. Best of all, you don’t even need an emulator to run it :)

April 21, 2011

Probably the biggest noticeable feature of Aeon 0.63 is support for emulating joysticks/gamepads through the PC game port. This was a pretty easy device to emulate, but hasn’t really been a priority for me since I basically never use game controllers on my PC. Turns out other people do though… Go figure :)

Anyway, the game port interface is actually pretty interesting in that it provides essentially no abstraction from the hardware. Learning how it worked made me finally understand what the deal was with every game needing calibration to work properly, and those weird dials on analog joysticks that I always had to fiddle with to keep the controls from drifting. If you already know how this works or don’t care, you won’t find this article very interesting, so you should probably stop now. Otherwise, read on…

Using a Joystick in DOS

DOS provides essentially no abstraction on anything except the disk (I guess that’s why it’s the Disk Operating System), so to work with the joystick, games would have to read a byte from the game port. Four of the bits of this byte are used to indicate the status of the first four buttons (or the first two buttons of each joystick if two are attached). The other four bits are used to indicate the position of the first four analog axes (again, or the first two of each joystick if two are attached).

Reading button status is easy enough: just look for whether the appropriate bit is cleared, which indicates that the button is pressed. Getting the position of an axis is another story.

You might wonder how an analog value can be transmitted using a single bit. The answer is: time. A DOS program first writes a value to the joystick port (any value will do), then immediately goes into a loop continuously reading the status byte. The axis bits will all start out at 1, and eventually will all drop to 0. The amount of time it takes for this to happen is proportional to the joystick’s position in that axis. The amount of time this takes is device dependent and can be measured in microseconds, so a game would count the number of iterations it takes for the value to drop to 0, rather than using timers or anything sophisticated like that.

Weird, isn’t it? Well, it turns out this makes a lot of sense.

The Hardware

I mentioned before how DOS provides no abstraction for most hardware devices, so you are left communicating with them directly most of the time. Most devices have some degrees of abstraction themselves, so this isn’t a huge problem, but the game port has essentially none. The classic joystick design that it works with was little more than a couple potentiometers (basically adjustable resistors if you are unfamiliar with circuits). Writing a value to the port causes some capacitors in the device to become charged. The speed this charge is lost depends on how much resistance is in the potentiometers (which is controlled by the joystick position and those crazy dials).

So that’s really all there is to it. A charge is placed on a circuit and the program waits for it to go away.

Emulation

For me, it was important to understand how programs would use the game port for me to emulate it properly. Fortunately, modern API’s make it a lot easier to read a joystick position, so it was trivial to query DirectInput for this. That means I just had to translate this value into something resembling a decaying voltage.

Fortunately, I knew that this charge decayed so quickly that DOS programs would generally just count iterations in a tight loop that looks something like this:

mov cx, 0 ; initialize cx to 0 for a counter
mov dx, 201h ; set game port 201h to the dx register
out dx,al ; write any value to the port
start: inc cx,1 ; increment cx register by 1
in al,dx ; read current status of the game port
test al,1 ; check whether the joystick 1 x-axis 1 bit is set
jnz start ; go to start if the bit is still set

So at the end of this loop, the CX register will contain the number of iterations it took for the bit to drop to 0. Knowing this, I can “cheat,” and just use a counter myself instead of doing any complicated high-resolution timing. All I have to do is scale the position of the joystick and decrement this value every time a program reads from the game port. When the value is greater than 0, Aeon returns a 1 for that axis; otherwise it returns a 0. This approach has worked perfectly in every game I’ve tried so far, and it was really easy.

Modern Controllers

Modern game controllers are more sophisticated than this – they are designed to communicate using USB or some other proprietary digital protocol and contain all of the logic needed to convert an analog position into a digital value, so fortunately modern game developers don’t have to be aware of the hardware implementation of how their input devices operate anymore. That’s fine with me. I for one have no desire to go back to the days of calibration and fidgeting with dials.

April 20, 2011

I’ve always been a fan of computer RPG’s, and usually the bigger the better. I first heard about the game Daggerfall years after its release and had a lot of trouble tracking it down, but had tons of fun with it once I did.

To be honest, I didn’t play the game so much as I played with it. The scope is huge, and the dungeons were randomly generated and extremely annoying (in my opinion). Also, it was a pretty buggy game – I remember an odd glitch that seemed to be unique to my computer at the time where my character was utterly incapable of falling; I would just glide in the air if I walked off an edge. Regardless of its problems, it’s still a fun sandbox to play in for a little while.

Bethesda (the company that made Daggerfall), released the game as freeware. You can download it from here. It runs pretty well in Aeon, provided you have a pretty fast machine.

Finally a new build! I guess I should really stop saying I’m going to update this blog more often. I’d like to… Well, I’m sure you’ve heard all of the standard excuses already, so on to the change list:

CD-ROM emulation is much more accurate when mounting a host drive or an iso

Host CD drive can now be captured

Minor performance improvements to a large number of instructions

Major performance increase for 4-plane video modes (EGA, Mode X)

Added support for launching commands with command.com /c

Fixed memory corruption issue when too many files were opened at once

Added "Check for Updates" option to Help menu

I finally added joystick support! It’s not very configurable yet – just giving you access to two axes and the first 4 buttons on any standard gamepad/controller/joystick. A more sophisticated button/key mapper will be added in a future version.

As usual, the download is here. I’ve redone the website as well. Hopefully most will consider this an improvement :)

Update: There is a bug in the installer that will report the incorrect version when upgrading. You’ll have to uninstall the old version first, then the install will run correctly.