ISHICORP Logo

Completing a Postponed Project

Published | Last updated

A black Dell OptiPlex workstation is on a carpet on the floor surrounded by power wires in the back with a black Dell computer CRT monitor placed on top turned on and displaying many green, yellow, and red circles of various sizes on a black background
BA-CREATURES executing from Windows XP running on a Dell OptiPlex GX260 with a Dell E773C monitor on top as a display

🔗Completing the Source Code

During the formative years of my interest in computing I explored several dialects of BASIC, including QBasic which had a popular following online. Through various community resources and documentation, my programming skill developed, confidence in my ability grew, and I sought ever more complex personal projects to tackle. One such project was BA-CREATURES, a virtual ecosystem simulation. I uploaded an early attempt to The QBasic Station on 23 April 2007.

I originally got this idea after reading an old book on Java Programming. I worked with the idea of having virtual pets, and then it spawned into a virtual ecosystem idea. So now here's BA-CREATURES. Right now it's just 5 circles, "creatures," moving around on the screen, but I plan on updating this often.

Despite my intention, I was unable to complete the project at the time due to my inexperience as a programmer, so I postponed it indefinitely. I revisited the project much later in 2021 and finally, having gained the necessary experience and grown significantly as a software engineer, I started over from scratch and did complete it on September 16, 2021.

However, while the source code was complete, I experienced my program only through a virtual machine emulation. I wondered what it would have been like to experience BA-CREATURES in 2007 as I originally had intended.

🔗Procuring the Hardware

I decided to acquire computer hardware similar to the kind with which I interacted during that era. The Dell OptiPlex line of computers were popular in my high school during that period of time, so I sought out a model that I could have encountered during my school days.

On eBay, I purchased a Dell OptiPlex GX260 desktop and Dell E773C CRT computer monitor.1 The desktop I purchased lacked a hard drive, so I also purchased a contemporary Western Digital WD800BB hard disk drive.

Incidentally, the Dell OptiPlex GX260 desktop arrived with visible signs of capacitor failure, such as a crusty orange electrolyte discharge on top of one capacitor and bulging capacitors (a known issue with this OptiPlex series). I worried that the system would not boot in this condition, but I was able to reach a BIOS configuration menu when I turned on the desktop, so cautiously I continued onward.

Although the Dell OptiPlex GX260 desktop I purchased did have a floppy disk drive and optical disc drive, I had only a digital backup of Windows XP Professional (Service Pack 2 included)2 saved as an ISO image file. Rather than purchase a new stack of blank CD-ROM discs that I am unlikely to use in the future, I decided to leverage a SanDisk Ultra SDCZ48-064G3 USB flash drive to boot the Windows XP installation program.

🔗Preparing the USB Flash Device

For a PC, booting from a USB flash drive follows a different procedure4 than booting from an optical disc drive. The Windows XP installation ISO image naturally contained an ISO 9660 file system with a Boot Record Volume Descriptor indicating a "El Torito" Bootable CD-ROM Format Specification, which meant it was bootable. However, because the PC BIOS will interpret the image differently if it is presented as a USB flash drive versus an optical disc drive, I could not simply write the ISO image verbatim to my USB flash drive.5

In order to boot the Windows XP installation program from my USB flash drive, I would need to format the drive with a Master Boot Record (MBR), install an appropriate bootloader, and copy over the necessary Windows XP installation files from the ISO image to a readable partition on the drive.

On my Fedora Linux system, I used the fdisk utility to partition the USB flash device (/dev/sda).

# fdisk /dev/sda

I created a new empty MBR (DOS) partition table, defined a single primary partition encompassing all available space, set the partition's type table entry to 0c for W95 FAT32 (LBA)6, and enabled the partition's boot flag7.

Disk /dev/sda: 57.3 GiB, 61530439680 bytes, 120176640 sectors
Disk model:  SanDisk 3.2Gen1
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xf0383d55

Device     Boot Start       End   Sectors  Size Id Type
/dev/sda1  *     2048 120176639 120174592 57.3G  c W95 FAT32 (LBA)

Next, I formatted the partition using the mkfs utility to create a MS-DOS FAT32 filesystem.

# mkfs.fat -F 32 /dev/sda1

This allowed me to mount the partition (/dev/sda1) to the /mnt directory on my system so I could transfer files over to the USB flash device.

The boot process of the Windows XP Setup goes through a number of phases. The relevant installation files are located under the I386 directory of the Windows XP installation CD. Of note, the SETUPLDR.BIN bootloader seems to look specifically for a $WIN_NT$.~BT folder at the root level of the booted partition; the Windows XP Setup program expects to find its installation files within this folder.

I used the xorriso utility to extract the necessary files from the Windows XP installation ISO image (VX2POEM_EN.ISO).

$ osirrox -indev VX2POEM_EN.ISO -extract /I386 /mnt/I386

Then I created a copy of the I386 directory as $WIN_NT$.~BT8, and copied the NTDETECT.COM and TXTSETUP.SIF files as well because they are also expected to exist under the root level of the booted partition.

$ cp -R /mnt/I386 /mnt/\$WIN_NT\$.~BT
$ cp /mnt/I386/NTDETECT.COM /mnt/
$ cp /mnt/I386/TXTSETUP.SIF /mnt/

Inside the TXTSETUP.SIF file, under the [SetupData] section I added a line for SetupSourceDevice specifying the boot partition (partition1) of my USB flash device (harddisk1).

--- a/TXTSETUP.SIF
+++ b/TXTSETUP.SIF
@@ -16302,3 +16302,3 @@
 [SetupData]
-
+SetupSourceDevice = \device\harddisk1\partition1
 

Finally, I installed the GNU GRUB bootloader to the USB flash device because it supported BIOS-based machines (i386-pc) and loading the Windows XP boot loader (NTLDR).

# grub2-install --target=i386-pc --boot-directory=/mnt/boot /dev/sda

The last step was to create a GRUB configuration file (/mnt/boot/grub2/grub.cfg) with a menu entry to search for the /$WIN_NT$.~BT/SETUPLDR.BIN file and load it.

menuentry "Windows XP Professional (Includes Service Pack 2) OEM installation" {
   set setupldr="/\$WIN_NT\$.~BT/SETUPLDR.BIN"
   search --set=root --file $setupldr
   ntldr $setupldr
}

🔗Hitting a Roadblock

I plugged the USB flash drive into the desktop and selected it from the BIOS boot menu. The GRUB menu appeared, so I selected the menu entry I created earlier and loaded the Windows XP Setup program.

The Windows Setup program loaded a number of files and, after some time, attempted to start Windows to load its drivers and begin the installation. Unfortunately, I encountered a blue screen of death (BSOD) thereafter.

Windows XP BSOD screen consisting of white Lucida Console text on blue background indicating that a problem has been detected and Windows has been shutdown
Windows XP stop error 0x0000007B screen

Stop error 0x0000007B corresponds to the INACCESSIBLE_BOOT_DEVICE bug check. As the name implies, Windows is unable to access the boot partition on the USB flash device.9

One way resolve this problem is to make adjustments to the Windows XP installation files to get Windows to load the necessary USB drivers earlier in its installation process so that they are available when needed. However, I was not inclined to make so many changes to the Windows XP installation files and spend time troubleshooting any further issues I encounter along the way.10

So I considered another way to get around this roadblock. Windows XP should load drivers appropriately to support the IDE hard disk drive, so I should be able to progress if I run the Windows installation from the IDE hard disk device instead.

🔗Preparing the Hard Disk

In order to format the hard disk, I would first need to boot into an appropriate operating system with the necessary tools. Starting with Fedora 31, bootable images for i686 systems were no longer provided, so instead I chose to write GParted Live11 to the USB flash device.

After booting into GParted Live on the OptiPlex GX260 desktop, I repeated the steps that I did for preparing the USB flash device on the IDE hard disk. However, I made the hard disk partition only 2 GB in size so that I could install Windows XP on the remainder of the drive.

Disk /dev/sda: 70.52 GiB, 75721927680 bytes, 147894390 sectors
Disk model: WDC WD800BB-55HE
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xa24dd20b

Device     Boot Start     End Sectors Size Id Type
/dev/sda1  *     2048 4196351 4194304   2G  c W95 FAT32 (LBA)

Also, I had to adjust the SetupSourceDevice line to specify the hard disk (harddisk0).

--- a/TXTSETUP.SIF
+++ b/TXTSETUP.SIF
@@ -16302,3 +16302,3 @@
 [SetupData]
-SetupSourceDevice = \device\harddisk1\partition1
+SetupSourceDevice = \device\harddisk0\partition1
 

I rebooted the desktop and booted from the hard disk. Windows XP Setup started and I was able to progress successfully past the previous BSOD. I continued the Windows installation process, formatting the remaining empty space on the drive as a NTFS partition.

🔗Running the Software

I finshed the Windows installation procedure and at last I was running Windows XP on the OptiPlex GX260 desktop. Windows XP was missing some drivers for the desktop, so I went to the Dell OptiPlex GX260 drivers page and downloaded the latest provided Intel 845G graphics driver (v.6.14.10.4544, A10). I installed the graphics driver and set the display mode to a True Color 1024x768 resolution.

I made one small change to the BA-CREATURES.BAS file. There is a SLEEP 1 line near the end of the game loop that I added to accommodate modern machines which generally run far faster than when QBasic was designed. I removed this line to experience BA-CREATURES as it would have been on a contemporary desktop.

diff --git a/BA-CREATURES.BAS b/BA-CREATURES.BAS
index 3e8976a..ad6b984 100644
--- a/BA-CREATURES.BAS
+++ b/BA-CREATURES.BAS
@@ -403,7 +403,5 @@ SUB runSimulation
 		CALL updateCreatures(auto(), numAuto, AUTOTROPH)
 		CALL updateCreatures(herb(), numHerb, HERBIVORE)
 		CALL updateCreatures(carn(), numCarn, CARNIVORE)
-
-		SLEEP 1
 	LOOP
 END SUB

Finally, I opened BA-CREATURES.BAS in QBasic 1.1 and ran it. I entered the following arbitrary configuration when prompted and started the simulation.

Initial health: 100
Growth rate: 10
Maximum health: 200
Consumption factor: 1
Starvation factor: 1
Wander force: 0.5
Flee force: 1
Chase force: 2
Maximum acceleration: 5
Maximum velocity: 8
Flee sense: 10
Chase sense: 20
Autotrophs: 50
Herbivores: 25
Carnivores: 13

It ran at a modest speed as expected, and slowed down to a crawl as the number of creatures increased, but it did run successfully as intended. I had achieved what I set out to do.

Despite the journey of setting up the prerequiste legacy hardware and software taking much more effort that I had anticipated, I felt statisfication at having brought a personal project from childhood through to completion. It is bittersweet to look back on old projects and think about how they fade away in time, whether physically as with the hardware degradation or just mentally in your mind. I'm glad I looked back on this one.