Wiki

Clone wiki

ultima-exodus / U3_Binary_Files

There are four categories of files in Ultima 3 that consist of binary executable code: game binaries, upgrade binaries, drivers, and world mods.

U3 Game Binaries

The following four program files ship with Ultima 3:

  • ULTIMA.COM - starts up the game, intro screens
  • BOOTUP.BIN - main menu
  • EXODUS.BIN - game code
  • DUNGEON.DAT - dungeon-specific code

ULTIMA.COM is a COM application which means that when it executes it loads the program into memory at cs:0100 and begins executing at that point. The data segment is ds=cs+0010 which means that the start of the program for data purposes is ds:0000. The program sets the video mode and begins the intro sequence including: the "EXODUS" logo, the "ULTIMA III" logo, the "by Lord British" text, and the animation of the heroes getting fried by a dragon. (spoiler!)

When the intro sequence completes, ULTIMA.COM loads BOOTUP.BIN in its place (at cs:0100) and begins executing it. BOOTUP.BIN is responsible for animating the demonstration window and controlling the main menu, including all roster maintenance.

When the player selects "Journey Onward" from the main menu, BOOTUP.BIN loads EXODUS.BIN in its place (again at cs:0100) and begins executing it. EXODUS.BIN is responsible for the majority of the game logic. The only exception to this is when the player enters a dungeon. In this case EXODUS.BIN loads DUNGEON.DAT in memory as a module and invokes it as necessary to render the dungeons. However even in this case, the player is still primarily interacting with the EXODUS.BIN logic.

The U3 Upgrade made extensive changes to all four of these binaries in order to support the upgrade-related features. The specific details on how the binaries were modified are included in the doc/u3tech subdirectory of the repository.

U3 Upgrade Binaries

The U3 upgrade adds two new binaries to coordinate upgrade-specific features.

  • ULTIMA3.COM - Launcher for the U3 Upgrade
  • U3CFG.EXE - U3 Upgrade configuration program

U3CFG.EXE is a text-base configuration program (with source code in C) that is used to toggle and/or configure features including graphics mode, music, sound effects, and game balance fixes. When configuration is saved, a U3.CFG file is generated with the selected settings. The source code for U3CFG.EXE is written in C and included in the tools/cfg subdirectory of the repository.

When ULTIMA3.COM is run, it loads U3.CFG and uses it to determine what drivers to load into memory. The location of those drivers (as well as any other configuration settings) are made available to the game via software interrupt 0x65. The source code for ULTIMA3.COM is written in assembly and included in the asm/launcher subdirectory of the repository.

Drivers

There are currently three categories of drivers:

  • Graphics Drivers
    • CGA.DRV - The CGA graphics driver
    • CGACOMP.DRV - A simulated CGA composite graphics driver
    • EGA.DRV - The EGA graphics driver
    • VGA.DRV - The VGA graphics driver
  • Music Drivers
    • MIDPAK.DRV - MIDI music driver that leverages Midpak
    • NOMIDI.DRV - Stub music driver that plays no music
  • Sound Effects Drivers
    • SFX.DRV - Default pc speaker sound effects driver
    • SFXTIMED.DRV - A pc speaker driver that regulates the speed of the sound effect

The driver files are loaded as needed by the ULTIMA3.COM launcher. The modified core binaries retrieve the segment address of the driver via int 0x65. The ULTIMA3.COM launcher expects to load exactly one of each category of driver.

When the game is ready to invoke a driver it does so by making a far call into the memory address of the function within the driver. Since the offset can change as we update the driver, we begin the driver with a series of jmp's into the actual function. For example, the start of VGA.DRV looks like:

cs:0000 E9E809   JMP 09EB
cs:0003 E9EE09   JMP 09F4
cs:0006 E9F409   JMP 09FD
cs:0009 E9FA09   JMP 0A06
...

Note that each jmp instruction is 3 bytes long. This means that when we want to make a far call into the driver we calculate the offset as the function number (numbered 0 to n-1) multiplied by 3. So for the third function, we'd call offset = 2*3 = 0006.

The source code for all the drivers is written in assembly and included in the asm/u3drv subdirectory of the repository.

World Mods

There are currently two world mods:

  • ULTIMA3.MOD - The original Ultima III
  • SOSARIA.MOD - Sosaria Mod / the Lands of Lord British

World mods are loaded, invoked, and structured identically to a driver, but are somewhat simpler with a focus on returning customized world data back to the game. (e.g. the location of towns, dungeons, moongates, exotics, etc)

The source code for all world mods is written in assembly and included in the asm/u3mod subdirectory of the repository.

Updated