Ultima IV internal formats

From Ultima Codex
(Redirected from Ultima IV Internal Formats)
Jump to navigation Jump to search

Introduction[edit]

This is a reference to the various files comprising the DOS version of Ultima IV.

EGA Files[edit]

These files contain the graphics used in the game. They can be uncompressed, run-length encoded, or LZW encoded. When uncompressed, each pixel value is represented by a 4-bit value indicating one of 16 colors:

Default EGA 16-color palette
(set up to match the standard CGA colors)
Color rgbRGB Decimal
0 – black (#000000) 000000 0
1 – blue (#0000AA) 000001 1
2 – green (#00AA00) 000010 2
3 – cyan (#00AAAA) 000011 3
4 – red (#AA0000) 000100 4
5 – magenta (#AA00AA) 000101 5
6 – brown (#AA5500) 010100 20
7 – white / light gray (#AAAAAA) 000111 7
8 – dark gray / bright black (#555555) 111000 56
9 – bright blue (#5555FF) 111001 57
10 – bright green (#55FF55) 111010 58
11 – bright cyan (#55FFFF) 111011 59
12 – bright red (#FF5555) 111100 60
13 – bright magenta (#FF55FF) 111101 61
14 – bright yellow (#FFFF55) 111110 62
15 – bright white (#FFFFFF) 111111 63

SHAPES.EGA[edit]

This file contains the bitmaps for all 256 tiles and is 32,768 bytes long. Each tile is 16x16 pixels, and each byte represents two pixels. Therefore, each tile is 128 bytes. In other words, the first 8 bytes represent the 16 pixels on the first row of the first tile (read left to right), and the next 8 bytes represent the 16 pixels on the second row of the first tile, and so on.

The EGA Tile set is :

Ultima 4 - Tiles.png


Offset Tile # Notes
0x0000 0 Deep Water
0x0080 1 Medium Water
0x0100 2 Shallow Water
0x0180 3 Swamp
0x0200 4 Grasslands
0x0280 5 Scrubland
0x0300 6 Forest
0x0380 7 Hills
0x0400 8 Mountains
0x0480 9 Dungeon Entrance
0x0500 10 Town
0x0580 11 Castle
0x0600 12 Village
0x0680 13 Lord British's Caste West
0x0700 14 Lord British's Castle Entrance
0x0780 15 Lord British's Castle East
0x0800 16 Ship West
0x0880 17 Ship North
0x0900 18 Ship East
0x0980 19 Ship South
0x0a00 20 Horse West
0x0a80 21 Horse East
0x0b00 22 Tile Floor
0x0b80 23 Bridge
0x0c00 24 Balloon
0x0c80 25 Bridge North
0x0d00 26 Bridge South
0x0d80 27 Ladder Up
0x0e00 28 Ladder Down
0x0e80 29 Ruins
0x0f00 30 Shrine
0x0f80 31 Avatar
0x1000 32 Mage 1
0x1080 33 Mage 2
0x1100 34 Bard 1
0x1180 35 Bard 2
0x1200 36 Fighter 1
0x1280 37 Fighter 2
0x1300 38 Druid 1
0x1380 39 Druid 2
0x1400 40 Tinker 1
0x1480 41 Tinker 2
0x1500 42 Paladin 1
0x1580 43 Paladin 2
0x1600 44 Ranger 1
0x1680 45 Ranger 2
0x1700 46 Shepherd 1
0x1780 47 Shepherd 2
0x1800 48 Column
0x1880 49 White SW
0x1900 50 White SE
0x1980 51 White NW
0x1a00 52 White NE
0x1a80 53 Mast
0x1b00 54 Ship's Wheel
0x1b80 55 Rocks
0x1c00 56 Lyin Down
0x1c80 57 Stone Wall
0x1d00 58 Locked Door
0x1d80 59 Unlocked Door
0x1e00 60 Chest
0x1e80 61 Ankh
0x1f00 62 Brick Floor
0x1f80 63 Wooden Planks
0x2000 64 Moongate 1
0x2080 65 Moongate 2
0x2100 66 Moongate 3
0x2180 67 Moongate 4
0x2200 68 Poison Field
0x2280 69 Energy Field
0x2300 70 Fire Field
0x2380 71 Sleep Field
0x2400 72 Solid Barrier
0x2480 73 Hidden Passage
0x2500 74 Altar
0x2580 75 Spit
0x2600 76 Lava Flow
0x2680 77 Missile
0x2700 78 Magic Sphere
0x2780 79 Attack Flash
0x2800 80 Guard 1
0x2880 81 Guard 2
0x2900 82 Citizen 1
0x2980 83 Citizen 2
0x2a00 84 Singing Bard 1
0x2a80 85 Singing Bard 2
0x2b00 86 Jester 1
0x2b80 87 Jester 2
0x2c00 88 Beggar 1
0x2c80 89 Beggar 2
0x2d00 90 Child 1
0x2d80 91 Child 2
0x2e00 92 Bull 1
0x2e80 93 Bull 2
0x2f00 94 Lord British 1
0x2f80 95 Lord British 2
0x3000 96 A
0x3080 97 B
0x3100 98 C
0x3180 99 D
0x3200 100 E
0x3280 101 F
0x3300 102 G
0x3380 103 H
0x3400 104 I
0x3480 105 J
0x3500 106 K
0x3580 107 L
0x3600 108 M
0x3680 109 N
0x3700 110 O
0x3780 111 P
0x3800 112 Q
0x3880 113 R
0x3900 114 S
0x3980 115 T
0x3a00 116 U
0x3a80 117 V
0x3b00 118 W
0x3b80 119 X
0x3c00 120 Y
0x3c80 121 Z
0x3d00 122 Space
0x3d80 123 Right
0x3e00 124 Left
0x3e80 125 Window
0x3f00 126 Blank
0x3f80 127 Brick Wall
0x4000 128 Pirate Ship West
0x4080 129 Pirate Ship North
0x4100 130 Pirate Ship East
0x4180 131 Pirate Ship South
0x4200 132 Nixie 1
0x4280 133 Nixie 2
0x4300 134 Giant Squid 1
0x4380 135 Giant Squid 2
0x4400 136 Sea Serpent 1
0x4480 137 Sea Serpent 2
0x4500 138 Seahorse 1
0x4580 139 Seahorse 2
0x4600 140 Whirlpool 1
0x4680 141 Whirlpool 2
0x4700 142 Storm 1
0x4780 143 Storm 2
0x4800 144 Rat 1
0x4880 145 Rat 2
0x4900 146 Rat 3
0x4980 147 Rat 4
0x4a00 148 Bat 1
0x4a80 149 Bat 2
0x4b00 150 Bat 3
0x4b80 151 Bat 4
0x4c00 152 Giant Spider 1
0x4c80 153 Giant Spider 2
0x4d00 154 Giant Spider 3
0x4d80 155 Giant Spider 4
0x4e00 156 Ghost 1
0x4e80 157 Ghost 2
0x4f00 158 Ghost 3
0x4f80 159 Ghost 4
0x5000 160 Slime 1
0x5080 161 Slime 2
0x5100 162 Slime 3
0x5180 163 Slime 4
0x5200 164 Troll 1
0x5280 165 Troll 2
0x5300 166 Troll 3
0x5380 167 Troll 4
0x5400 168 Gremlin 1
0x5480 169 Gremlin 2
0x5500 170 Gremlin 3
0x5580 171 Gremlin 4
0x5600 172 Mimic 1
0x5680 173 Mimic 2
0x5700 174 Mimic 3
0x5780 175 Mimic 4
0x5800 176 Reaper 1
0x5880 177 Reaper 2
0x5900 178 Reaper 3
0x5980 179 Reaper 4
0x5a00 180 Insect Swarm 1
0x5a80 181 Insect Swarm 2
0x5b00 182 Insect Swarm 3
0x5b80 183 Insect Swarm 4
0x5c00 184 Gazer 1
0x5c80 185 Gazer 2
0x5d00 186 Gazer 3
0x5d80 187 Gazer 4
0x5e00 188 Phantom 1
0x5e80 189 Phantom 2
0x5f00 190 Phantom 3
0x5f80 191 Phantom 4
0x6000 192 Orc 1
0x6080 193 Orc 2
0x6100 194 Orc 3
0x6180 195 Orc 4
0x6200 196 Skeleton 1
0x6280 197 Skeleton 2
0x6300 198 Skeleton 3
0x6380 199 Skeleton 4
0x6400 200 Rogue 1
0x6480 201 Rogue 2
0x6500 202 Rogue 3
0x6580 203 Rogue 4
0x6600 204 Python 1
0x6680 205 Python 2
0x6700 206 Python 3
0x6780 207 Python 4
0x6800 208 Ettin 1
0x6880 209 Ettin 2
0x6900 210 Ettin 3
0x6980 211 Ettin 4
0x6a00 212 Headless 1
0x6a80 213 Headless 2
0x6b00 214 Headless 3
0x6b80 215 Headless 4
0x6c00 216 Cyclops 1
0x6c80 217 Cyclops 2
0x6d00 218 Cyclops 3
0x6d80 219 Cyclops 4
0x6e00 220 Wisp 1
0x6e80 221 Wisp 2
0x6f00 222 Wisp 3
0x6f80 223 Wisp 4
0x7000 224 Evil Mage 1
0x7080 225 Evil Mage 2
0x7100 226 Evil Mage 3
0x7180 227 Evil Mage 4
0x7200 228 Lich 1
0x7280 229 Lich 2
0x7300 230 Lich 3
0x7380 231 Lich 4
0x7400 232 Lava Lizard 1
0x7480 233 Lava Lizard 2
0x7500 234 Lava Lizard 3
0x7580 235 Lava Lizard 4
0x7600 236 Zorn 1
0x7680 237 Zorn 2
0x7700 238 Zorn 3
0x7780 239 Zorn 4
0x7800 240 Daemon 1
0x7880 241 Daemon 2
0x7900 242 Daemon 3
0x7980 243 Daemon 4
0x7a00 244 Hydra 1
0x7a80 245 Hydra 2
0x7b00 246 Hydra 3
0x7b80 247 Hydra 4
0x7c00 248 Dragon 1
0x7c80 249 Dragon 2
0x7d00 250 Dragon 3
0x7d80 251 Dragon 4
0x7e00 252 Balron 1
0x7e80 253 Balron 2
0x7f00 254 Balron 3
0x7f80 255 Balron 4

CHARSET.EGA[edit]

This contains the bitmaps for each character in the font. Each character is 8x8 pixels, and each byte represents two pixels. In other words, the first 4 bytes represent the 8 pixels on the first row of the first character.

The EGA Character Set is:

Ultima 4 Character Set.png


Offset Length Notes
0x0 32 character 0
0x20 32 character 1
0x40 32 character 2
... ... ...
0x1FC0 32 character 255

The order is the standard ASCII mapping; 'A' is character 65, 'z' is character 122. The lowest 32 characters have the following glyphs:

# Name
0 Ankh
1 Symbol for horn effect
2 Brick wall 1
3 Brick wall 2
4 Updown arrow
5 Down arrow
6 Up arrow
7 Partial ankh
8 Filled circle
9 Copyright
10 Registered trademark
11 Male symbol
12 Female symbol
13 Border bar
14 Hollow square
15 ?
16 Border endpiece (right)
17 Border endpiece (left)
18 ?
19 Ellipsis
20 Moon phase 0
21 Moon phase 1
22 Moon phase 2
23 Moon phase 3
24 Moon phase 4
25 Moon phase 5
26 Moon phase 6
27 Moon phase 7
28 Cursor image 1
29 Cursor image 2
30 Cursor image 3
31 Cursor image 4

Run-Length Encoded EGA Files[edit]

The following .EGA files are RLE encoded: START.EGA, KEY7.EGA, RUNE_x.EGA (where x is between 0 and 5), STONCRCL.EGA, HONESTY.EGA, COMPASSN.EGA, VALOR.EGA, JUSTICE.EGA, SACRIFIC.EGA, HONOR.EGA, SPIRIT.EGA, HUMILITY.EGA, TRUTH.EGA, LOVE.EGA, and COURAGE.EGA. Each of these files represents a 16 color 320x200 bitmap. Each pixel is encoded in 4 bits, like SHAPES.EGA and CHARSET.EGA. However, runs of identical *bytes* (not pixels) are encoded with a special run indicator value (0x02) followed by a one byte count and a one byte value. This allows a single run of up to 255 bytes (510 pixels) to be represented as three bytes. For example, the byte values "28 28 28 28" could be represented as "02 04 28". If the value 0x02 needs to be represented, it *must* be encoded in a run ("02 01 02").

File Purpose
START.EGA The basic game borders
KEY7.EGA Shown when the key is used
RUNE_0.EGA Vision shown after meditating on valor
RUNE_1.EGA Vision shown after meditating on honesty, justice, and honor
RUNE_2.EGA Vision shown after meditating on compassion and sacrifice
RUNE_3.EGA Vision shown after meditating on spirituality
RUNE_4.EGA Vision shown after meditating on humility
RUNE_5.EGA Vision after answering the final riddle in the Stygian Abyss
STONCRCL.EGA Shown when game completed
HONESTY.EGA Shown during questioning in abyss
COMPASSN.EGA Shown during questioning in abyss
VALOR.EGA Shown during questioning in abyss
JUSTICE.EGA Shown during questioning in abyss
SACRIFIC.EGA Shown during questioning in abyss
HONOR.EGA Shown during questioning in abyss
SPIRIT.EGA Shown during questioning in abyss
HUMILITY.EGA Shown during questioning in abyss
TRUTH.EGA Shown during questioning in abyss
LOVE.EGA Shown during questioning in abyss
COURAGE.EGA Shown during questioning in abyss

LZW Encoded EGA Files[edit]

The remaining .EGA files are LZW encoded: ABACUS.EGA, ANIMATE.EGA, GYPSY.EGA, INSIDE.EGA, OUTSIDE.EGA, PORTAL.EGA, TREE.EGA, WAGON.EGA, HONCOM.EGA, SACHONOR.EGA, SPIRHUM.EGA, VALJUS.EGA, and TITLE.EGA. Also, the file SHAPES.EGZ is a LZW compressed version of SHAPES.EGA. Like the RLE encoded files, each of these files represents a 16 color 320x200 bitmap. LZW encoded files only seem to be used in the introduction sequence (i.e. in TITLE.EXE); the images used by AVATAR.EXE are RLE encoded instead.

For more details on the LZW algorithm: Lempel-Ziv-Welch


File Purpose
ABACUS.EGA The abacus that serves as the background while the questions are asked
ANIMATE.EGA The frames for the little critters in the upper corners of the intro screen
GYPSY.EGA The gypsy herself
HONCOM.EGA The cards for honor and compassion
INSIDE.EGA Inside the fair
OUTSIDE.EGA The fair from outside
PORTAL.EGA Closeup of the moongate
SACHONOR.EGA The cards for sacrifice and honor
SPIRHUM.EGA The cards for spirituality and humility
TITLE.EGA The background for the inital screen, including the large Ultima IV and the border for the map/menu
TREE.EGA Initial graphic for character creation sequence (has animated moongate)
VALJUS.EGA The cards for valor and justice
WAGON.EGA The gyspy's wagon

WORLD.MAP[edit]

This is the map of Britannia. It is 256x256 tiles in total and broken up into 64 32x32 chunks; the total file is 65,536 bytes long. The first chunk is in the top left corner; the next is just to the right of it, and so on. The last chunk is in the bottom right corner. Each tile is stored as a byte that maps to a tile in SHAPES.EGA. The chunks are stored in the same way as the overall map: left to right and top to bottom.

The "chunked" layout is an artifact of the limited memory on the original machines that ran Ultima IV. The whole map would take 64kb, too much for a C64 or an Apple II, so the game would keep a limited number of 1k chunks in memory at a time. As the player moved around, old chunks were thrown out as new ones were swapped in.

Offset Length (in bytes) Notes
0x0 1024 32x32 map matrix for chunk 0
0x400 1024 32x32 map matrix for chunk 1
... ... ...
0xFC00 1024 32x32 map matrix for chunk 63

ULT files[edit]

These contain town information. Specifically, a 32x32 map, plus the starting position, movement behavior, and conversation index of each NPC. The conversation index gives the starting position of the NPC's dialog block in the corresponding .TLK file. I'm not sure why some of the data is duplicated.

Offset Length (in bytes) Notes
0x0 1024 32x32 Town Map Matrix
0x400 32 Tile index for NPCs 0-31
0x420 32 Start_x for NPCs 0-31
0x440 32 Start_y for NPCs 0-31
0x460 32 Unused? - Same structure as monster.sav so previous tile?
0x480 32 Unused? - Same structure as monster.sav so previous x?
0x4A0 32 Unused? - Same structure as monster.sav so previous y?
0x4C0 32 Movement Behavior for NPCs 0-31
0x4E0 32 1-based conversation index (in the corresponding tlk file) for NPCs 0-31. 0 indicates no tlk record.

Movement Behavior[edit]

Byte Value Type
0x00 Fixed
0x01 Wander
0x80 Follow
0xFF Attack

TLK files[edit]

These files contain the dialogue for up to 16 NPCs in a given area. Each NPC has a 288 (0x120) byte block containing his or her dialogues, followed by the keywords that trigger his or her responses. Most of the fields are null-terminated, variable length strings, with the following field starting immediately after. The blocks are then padded with zero bytes to 288 bytes. See also Ultima IV transcript.

Offset Length (in bytes) Purpose
0x0 1 Question Flag (3=JOB, 4=HEALTH, 5=KEYWORD1, 6=KEYWORD2)
0x1 1 Does Response Affect Humility? (0=No, 1=Yes)
0x2 1 Probability of Turning Away (out of 256)
0x3 Varies Name
Varies Varies Pronoun (He, She or It)
Varies Varies LOOK Description
Varies Varies JOB Response
Varies Varies HEALTH Response
Varies Varies KEYWORD 1 Response
Varies Varies KEYWORD 2 Response
Varies Varies Yes/No Question
Varies Varies YES Response
Varies Varies NO Response
Varies Varies KEYWORD 1
Varies Varies KEYWORD 2
Varies-0x119 Varies 00000....

CON files[edit]

These files contain the 11x11 battleground maps shown when combat starts. It has the map itself plus starting positions for up to 16 monsters and 8 party members.

Offset Length (in bytes) Purpose
0x0 16 start_x for monsters 0-15
0x10 16 start_y for monsters 0-15
0x20 8 start_x for party members 0-7
0x28 8 start_y for party members 0-7
0x30 16 Purpose unknown; seems to be a constant: 08 AD 83 C0 AD 83 C0 AD 83 C0 A0 00 B9 A6 08 F0
0x40 121 11x11 Map Matrix
0xB9 7 Purpose unknown; seems to be a constant: 8D 00 00 00 00 47 09

DNG files[edit]

These files define each of the dungeons. The standard file size is 4,608 bytes. ABYSS.DNG is 16,896 bytes.

3D Dungeon Map[edit]

The first 512 bytes are the 8x8 maps for each of the 8 levels. These are used for the dungeons in 3D mode. They are read, as usual, from left to right and then top to bottom.

Offset Length (in bytes) Purpose
0x0 64 Level 1 Map Matrix
0x40 64 Level 2 Map Matrix
0x80 64 Level 3 Map Matrix
0xC0 64 Level 4 Map Matrix
0x100 64 Level 5 Map Matrix
0x140 64 Level 6 Map Matrix
0x180 64 Level 7 Map Matrix
0x1C0 64 Level 8 Map Matrix

Dungeon Floor Tiles[edit]

Each point on the grid can be one of several types.

Value Type
00 Nothing
10 Ladder Up
20 Ladder Down
30 Laddr Up & Down
40 Treasure Chest
50 Ceiling Hole
60 Floor Hole (unused)
70 Magic Orb
80 Winds/Darknes Trap
81 Falling Rock Trap
8E Pit Trap
90 Plain Fountain
91 Healing Fountain
92 Acid Fountain
93 Cure Fountain
94 Poison Fountain
A0 Poison Field
A1 Energy Field
A2 Fire Field
A3 Sleep Field
B0 Altar
C0 Door
D0-DF Dungeon Rooms 0-15
E0 Secret Door
F0 Wall

ABYSS.DNG Map Format[edit]

The Stygian Abyss also follows the same format with one important caveat: since it has 64 rooms instead of 16, several levels share D# values. Levels 1&2 each have eight rooms. Levels 3&4 each have eight rooms. Level 5 has 5 rooms, and Level 6 has 11 rooms. Level 7 has 4 rooms, and Level 8 has 12 rooms. The D# values still define the order the rooms appear; they simply reset every two dungeon levels.

Dungeon Rooms[edit]

The rest of the file is a set of 16 (64 in the case of the ABYSS.DNG) 256 byte blocks that define the dungeon rooms.

Offset Length (in bytes) Purpose
0x200 256 Room 0 Data
0x300 256 Room 1 Data
0x400 256 Room 2 Data
0x500 256 Room 3 Data
0x600 256 Room 4 Data
... ... ...
0x1100 256 Room 15 Data

ABYSS.DNG only[edit]

Offset Length (in bytes) Purpose
0x200 256 Room 0 Data
0x300 256 Room 1 Data
0x400 256 Room 2 Data
0x500 256 Room 3 Data
0x600 256 Room 4 Data
... ... ...
0x1100 256 Room 15 Data
0x1200 256 Room 16 Data
0x1300 256 Room 17 Data
... ... ...
0x4100 256 Room 63 Data


Dungeon Room Format[edit]

Offset Length (in bytes) Purpose
0x0 16 floor triggers (4 bytes each X 4 triggers possible)
0x10 16 tile for monsters 0-15 (0 means no monster and 0's come FIRST)
0x20 16 start_x for monsters 0-15
0x30 16 start_y for monsters 0-15
0x40 8 start_x for party member 0-7 (north entry)
0x48 8 start_y for party member 0-7 (north entry)
0x50 8 start_x for party member 0-7 (east entry)
0x58 8 start_y for party member 0-7 (east entry)
0x60 8 start_x for party member 0-7 (south entry)
0x68 8 start_y for party member 0-7 (south entry)
0x70 8 start_x for party member 0-7 (west entry)
0x78 8 start_y for party member 0-7 (west entry)
0x80 121 11x11 map matrix for room
0xF9 7 buffer
Trigger format[edit]
Offset Length (in bytes) Purpose
0x0 1 tile to be placed
0x1 1 2 nibbles indicating the (x,y) coords of trigger
0x2 1 2 nibbles indicating the (x,y) coords of 1st tile to change
0x3 1 2 nibbles indicating the (x,y) coords of 2nd tile to change

All 0's indicate no trigger. "No trigger" records come last.

TRIGGER EXAMPLE: 0x45 0x85 0x75 0x65 - Places a Lightning Field (tile #69) at locations (7, 5) and (6, 5) when you step on location (8, 5).

SAV Files[edit]

These files save the state of the program between sessions.

PARTY.SAV[edit]

This file stores the information that is stored when the game is saved. It includes party-wide information like gold and food, plus a 39 byte record for each character.

Offset Length (in bytes) Purpose
0x0 4 Counter (incremented regularly, probably every screen update)
0x4 2 Moves (low word)
0x6 2 Moves (high word)
0x8 39 Player 0 record
0x2F 39 Player 1 record
0x56 39 Player 2 record
0x7D 39 Player 3 record
0xA4 39 Player 4 record
0xCB 39 Player 5 record
0xF2 39 Player 6 record
0x119 39 Player 7 record
0x140 4 Food (in units of hundredths)
0x144 2 Gold
0x146 16 Karma (2 bytes each for honesty, compassion, valor, justice, sacrifice, honor, spirituality and humility; 0-partial avatar)
0x156 2 Torches
0x158 2 Gems
0x15A 2 Keys
0x15C 2 Sextants
0x15E 16 Armor (2 bytes each for none (unused), cloth, leather, chain, plate, magic chain, magic plate, mystic robes)
0x16E 32 Weapons (2 bytes each for none (unused), staves, daggers, slings, maces, axes, swords, bows, crossbows, oil, halberds, magic axes, magic swords, magic bows, magic wands, mystic swords)
0x18E 16 Reagents (2 bytes each for sulfurous ash, ginseng, garlic, spider silk, blood moss, black pearl, nightshade, mandrake)
0x19E 52 Mixtures (2 bytes each for awaken, blink, cure, dispel, energy, fireball, gate, heal, iceball, jinx, kill, light,magic missile, negate, open, protection, quickness, resurrect, sleep, tremor, undead, view, winds, x-it, y-up, z-down)
0x1D2 1 Items (1 bit each for skull, skull destroyed, candle, book, bell, key part C, key part L, key part T)
0x1D3 1 Items (1 bit each for horn, wheel, candle used at abyss entrance, book used at abyss entrance, bell used at abyss entrance, (3 bits unused))
0x1D4 1 X coordinate
0x1D5 1 Y coordinate
0x1D6 1 Stones (1 bit each for BYRGOPWB)
0x1D7 1 Runes (1 bit each for HCVJSHSH)
0x1D8 2 Number of characters in party
0x1DA 2 Transportation (0x10-ship facing west, 0x11-ship facing north, 0x12-ship facing east, 0x13-ship facing south, 0x14-horse facing west, 0x15-horse facing east, 0x18-balloon, 0x1f-on foot)
0x1DC 2 On surface: balloon status (0-on ground, 1-flying) in dungeon: current torch duration
0x1DE 2 Current phase of left moon (Trammel); range = 0-7
0x1E0 2 Current phase of right moon (Felucca); range = 0-7
0x1E2 2 Hull integrity of currently boarded ship if you x-it a ship, save, restart the game, and board the ship again, you will find that all damage to the ship has been mysteriously repaired.
0x1E4 2 Introduced to Lord British (0-haven't been introduced, 1-introduced)
0x1E6 2 Time of last successful hole up & camp. The game stores ((moves / 0x64) & 0xffff) in this field when you successfully hole up & camp. If (moves / 0x64) < 0x10000: You can only hole up & camp successfully if the current ((moves / 0x64) & 0xffff) is different from the value in this field. If (moves / 0x64) >= 0x10000: Hole up & camp is always successful.
0x1E8 2 Time of last mandrake/nightshade find. The game stores (moves & 0xf0) in this field when you find mandrake/nightshade. You can only find mandrake/nightshade if the current (moves & 0xf0) is different from the value in this field.
0x1EA 2 Time of last successful meditation at a shrine. The game stores ((moves / 0x64) & 0xffff) in this field when you successfully meditate at a shrine. If (moves / 0x64) < 0x10000: You can only meditate successfully if the current ((moves / 0x64) & 0xffff) is different from the value in this field. If (moves / 0x64) >= 0x10000: Meditating at a shrine is always successful.
0x1EC 2 Time of last virtue-related conversation. The game stores ((moves / 0x10) & 0xffff) in field when one of the following happens: (1) you give gold to a beggar, (2) you answer a yes/no question from an NPC (doesn't have to be a question where the answer affects your virtue). If ((moves / 0x10) & 0xffff) < 0x10000: Giving gold to a beggar or answering a virtue-related yes/no question only increases your karma if ((moves / 0x10) & 0xffff) is different from the value in this field. If ((moves / 0x10) & 0xffff) >= 0x10000: Giving gold or answering a virtue question always increases your karma.
0x1EE 2 If the party is in a dungeon: coordinates of this dungeon, if not: coordinates of the dungeon last entered by the party
0x1F0 2 Orientation in dungeon (0-west, 1-north, 2-east, 3-south)
0x1F2 2 Dungeon level (starting at zero, 0xffff = surface)
0x1F4 2 Current party location (see below)

Character Record Format[edit]

Offset Length (in bytes) Purpose
0x0 2 HP
0x2 2 Maximum HP
0x4 2 XP
0x6 2 Strength
0x8 2 Dexterity
0xA 2 Intelligence
0xC 2 MP
0xE 2 ???
0x10 2 Weapon
0x12 2 Armor
0x14 16 Name
0x24 1 Sex (0xb-male, 0xc-female)
0x25 1 Class
0x26 1 Status ('G'-good, 'P'-poisoned, 'S'-sleeping, 'D'-dead)

Party Location[edit]

Since you can only save on the surface or in a dungeon, the only valid party locations are 0 and 0x11-0x18.

Value Location
0x00 Surface
0x01 Lord British's castle
0x02 The Lycaeum
0x03 Empath Abbey
0x04 Serpent's Hold
0x05 Moonglow
0x06 Britain
0x07 Jhelom
0x08 Yew
0x09 Minoc
0x0A Trinsic
0x0B Skara Brae
0x0C Magincia
0x0D Paws
0x0E Buccaneer's Den
0x0F Vesper
0x10 Cove
0x11 Deceit
0x12 Despise
0x13 Destard
0x14 Wrong
0x15 Covetous
0x16 Shame
0x17 Hythloth
0x18 Abyss
0x19 Shrine of Honesty
0x1A Shrine of Compassion
0x1B Shrine of Valor
0x1C Shrine of Justice
0x1D Shrine of Sacrifice
0x1E Shrine of Honor
0x1F Shrine of Spirituality
0x20 Shrine of Humility

MONSTERS.SAV[edit]

Ultima IV maintains a structure (in memory) that I've decided to call the "monster table." When you Journey Onward, U4 loads MONSTERS.SAV into the monster table. When you Quit & Save, U4 writes the monster table to MONSTERS.SAV. The purpose of the monster table fields depends on the current party location (surface, dungeon, settlement).

Surface[edit]

On the surface, the monster table contains information about monsters and inanimate objects (chests, horses, ships, balloon). A table entry is free if previousTile[i]==0. When u4dos deletes an entry, it sets both currentTile[i] and previousTile[i] to 0. Slots 0-7 are for monsters, while slots 8-31 are for inanimate objects. Non-empty entries don't have to be contiguous. Whirlpools and twisters are special cases; they must be placed in slot 0-3, or they won't swallow ships / damage the party. When you leave Hythloth, u4dos creates the balloon at (233 / 242). If there is more than one inanimate object on a tile, objects closer to the beginning of the table are drawn on top of those closer to the end. Monsters and the party are always drawn on top of inanimate objects. The current tile and previous tile values are used during runtime. However, when the game is saved, the previous tile must be set to the monster's base tile. The current tile can be any of the monster's tiles, except for pirate ships, where the current tile determines which direction the pirate ship is facing. If the previous tile is not set to the monster's base tile, it won't behave properly in u4dos: monsters with ranged attacks won't use them in combat, twisters and whirlpools will attack the party, and pirates will appear as pirate ships in battle. For transports with more than one tile (horse, ship), the previous tile determines which direction the transport is facing, while the current tile can be any of the transport's tiles.

Offset Length (in bytes) Purpose
0x0 32 Current Tile #s
0x20 32 X Coordinates For Current Turn
0x40 32 Y Coordinates For Current Turn
0x60 32 Tile #s For Previous Turn
0x80 32 X Coordinates For Previous Turn
0xA0 32 Y Coordinates For Previous Turn
0xC0 32 Unused
0xE0 32 Unused

Dungeons[edit]

In a dungeon, the monster table contains information about the monsters in the dungeon. A monster stored in the monster table is *also* stored in DNGMAP.SAV. Inanimate objects are not stored in the monster table; they are stored *only* in DNGMAP.SAV.

Offset Length (in bytes) Purpose
0x0 32 Unused
0x20 32 X Coordinate For Current Turn
0x40 32 Y Coordinate For Current Turn
0x60 32 Current Tile #
0x80 32 X Coordinate For Previous Turn
0xA0 32 Y Coordinate For Previous Turn
0xC0 32 Dungeon Level (Range: 0-7)
0xE0 32 Unused

Settlements[edit]

In a castle/town/village, the monster table is loaded from the settlements’ .ULT file, starting at offset 0x400. It contains information about the settlements’ NPCs.

Offset Length (in bytes) Purpose
0x0 32 Current Tile #
0x20 32 X Coordinate For Current Turn
0x40 32 Y Coordinate For Current Turn
0x60 32 Tile # For Previous Turn
0x80 32 X Coordinate For Previous Turn
0xA0 32 Y Coordinate For Previous Turn
0xC0 32 Movement Behavior For NPCs 0-31 (0x0-fixed, 0x1-wander, 0x80-follow, 0xFF-attack)
0xE0 32 Conversation Index (.tlk file) For NPCs 0-31

OUTMONST.SAV[edit]

OUTMONST.SAV is a backup of the monster table, created when you enter a dungeon or settlement. When you leave a dungeon or settlement, the monster table is reloaded from OUTMONST.SAV.

Exception: When you enter Hythloth through the ladder in LB's castle, the game does not write the current monster table to OUTMONST.SAV, because it already did that when you entered LB's castle.

DNGMAP.SAV[edit]

When you Quit & Save in a dungeon, the game saves objects (orbs, chests) and monsters in DNGMAP.SAV. DNGMAP.SAV contains the 8x8 maps for all 8 levels. Every tile is encoded as a byte. The upper nibble of a tile determines the tile type (see below). The lower nibble encodes the monster standing on the tile, except for tiles 0x80 0x90 0xA0 0xD0 (see below).

Value Purpose
0x00 Nothing
0x10 Ladder Up
0x20 Ladder Down
0x30 Ladder Up/Down
0x40 Chest
0x50 Hole in Ceiling (unused)
0x60 Hole in Floor (unused)
0x70 Orb (see below)
0x80 Wind/Darkness Trap (magic winds)
0x81 Falling Rocks Trap (falling rocks)
0x8E Pit Trap
0x90 Ordinary Fountain (no effect)
0x91 Healing Fountain (restores all HP)
0x92 Acid Fountain (100 HP damage)
0x93 Curing Fountain (cures poison)
0x94 Poisoned Fountain (poison and 100 HP damage)
0xA0 Poison Field
0xA1 Energy Field
0xA2 Fire Field
0xA3 Sleep Field
0xB0 Altar (stone color depends on dungeon)
0xC0 Door
0xD0-0xDF Dungeon Rooms 0-15
0xE0 Hidden Door
0xF0 Wall

Monsters[edit]

Value Purpose
0x0 None
0x1 Rat
0x2 Bat
0x3 Spider
0x4 Ghost
0x5 Slime
0x6 Troll
0x7 Gremlin
0x8 Mimic
0x9 Reaper
0xA Insect Swarm
0xB Gazer
0xC Phantom
0xD Orc
0xE Skeleton
0xF Rogue

Orbs[edit]

When a PC touches an orb, one or more attributes are raised by 5 points each. Which attributes are raised depends on the dungeon.

Dungeon Attributes
Deceit INT
Despise DEX
Destard STR
Wrong INT,DEX
Covetous DEX,STR
Shame INT,DEX
Hythloth INT,DEX,STR

EXE Files[edit]

These files are the executable programs that power the game. They also contain some data that does not fit elsewhere.

TITLE.EXE[edit]

This executable is launched by ULTIMA.COM to display the introduction and create new characters. When "Journey Onward" is selected from the intro menu, it exits and ULTIMA.COM passes control off to AVATAR.EXE, the main game executable. AVATAR.EXE has lots of the data necessary for the intro screens embedded in it.

Offset Length (in bytes) Purpose
0x0 17445 ???
0x4425 11088 Text for Introduction, Gypsy Dialog and Gyspy Questions (null-terminated strings)
0x6f75 1035 ???
0x70dc 8 Starting x positions for a new game
0x70e4 8 Starting y positions for a new game[1]
0x7380 184 List of Frames Sequences for Beasties on Intro Screen
0x7438 54 ???
0x746e 532 266 X/Y Coordinates for the pixels that make up the Lord British signature on the introductory title screen
0x7682 1 Zero Terminating Byte
0x7683 95 Tile Values for the 19x5 map that appears on the introductory title screen
0x76e2 548 Script Data for the intro map animations
0x7906 ... ???

AVATAR.EXE[edit]

This is the main game executable, launched from ultima.com (or run on its own to skip the intro). Lots of the special case data is embedded in it.

Offset Length (in bytes) Purpose
0x0 25123 ???
0x06223 1 Everything this value and below can't be used in the Abyss
0x0 38719 ???
0x0f963 1 volume on/off flag
0x0f964 27 13 two-byte code pointers to 13 sound generation routines plus one padding byte
0x0f97f 171 .ULT filenames; 16 zero terminated strings
0x0fa2a 48 stone colors; 8 zero terminated strings
0x0fa5a 91 .DNG filenames; 8 zero terminated strings
0x0fab5 28 ???
0x0fad1 8 moongate x-coordinates (one byte for each moongate starting at Moonglow)
0x0fad9 8 moongate y-coordinates (one byte for each moongate starting at Moonglow)
0x0fae1 32 16 two-byte offsets to .ULT filenames (value + 62141 gives file offset)
0x0fb01 32 area x-coordinates (one byte for each town, city, castle, dungeon, shrine)
0x0fb21 32 area y-coordinates (one byte for each town, city, castle, dungeon, shrine)
0x0fb41 16 8 two-byte offsets to stone colors (value + 62141 gives file offset)
0x0fb51 16 8 two-byte offsets to .DNG filenames (value + 62141 gives file offset)
0x0fb61 72 ???
0x0fba9 8 pirates cove ship x coordinates
0x0fbb1 8 pirates cove ship y coordinates
0x0fbb9 8 pirates cove ship tiles
0x0fbc1 37 zero terminated list of tiles that are walkable
0x0fbe6 149 14 zero-terminated navigation strings ("North", "Sail North", etc.)
0x0fc7b 539 Chamber of the Codex virtue questions
0x0fe96 78 ???
0x0fee4 647 Chamber of the Codex dialog strings
0x1016b 28 ???
0x10187 509 Chamber of the Codex dialog strings
0x10384 83 ???
0x103d7 1280 abyss question dialog strings
0x108d7 22 11 two-byte offsets to abyss question answers (value + 62141 gives file offset)
0x108ed 80 ???
0x1093d 169 .TLK filenames; 16 zero terminated strings
0x109e6 13 "OUTMONST.SAV" zero terminated string
0x109f3 32 16 two-byte offsets to .TLK filenames (value + 62139 gives file offset)
0x10a13 659 ???
0x10ca6 246 monster names; 36 zero terminated strings
0x10d9c 129 weapon names; 16 zero terminated strings
0x10e1d 77 armor names; 8 zero terminated strings
0x10e6a 64 weapon abbreviations; 16 zero terminated strings
0x10eaa 55 character class names; 8 zero terminated strings
0x10ee1 58 npc type names; 8 zero terminated strings
0x10f1b 81 reagent names; 8 zero terminated strings
0x10f6c 434 spell names; 26 zero terminated strings
0x1101e 292 castle/city/town/dungeon/shrine names; 32 zero terminated strings
0x11142 11 ???
0x1114d 72 36 two-byte offsets to monster names (value + 62131 gives file offset)
0x11195 32 16 two-byte offsets to weapon names (value + 62131 gives file offset)
0x111b5 16 8 two-byte offsets to armor names (value + 62131 gives file offset)
0x111c5 32 16 two-byte offsets to weapon abbreviations (value + 62131 gives file offset)
0x111e5 16 8 two-byte offsets to character class names (value + 62131 gives file offset)
0x111f5 330 ???
0x1133f 26 mp required for each spell (one byte per spell)
0x11359 654 ???
0x115e7 16 mask of which classes can use each weapon (one byte per weapon)
0x115f7 8 mask of which classes can use each type of armor (one byte per armor type)
0x115ff 134 ???
0x11685 52 monster hp table
0x116b9 36 monster leader types (one byte per monster type)
0x116dd 36 monster encounter size table (one byte per monster type)
0x11701 2 ???
0x11703 16 weapon damage list (one byte per weapon type)
0x11713 8 armor defense list (one byte per armor type)
0x1171b 16 weapon category list (one byte per weapon type; 0 = melee, 0xff = missile)
0x1172b 154 .CON filenames; 14 zero terminated strings
0x117c5 28 14 two-byte offsets to .CON filenames (value + 62131 gives file offset)
0x117e1 64 dungeon .CON filenames; 7 zero terminated strings
0x11821 164 ???
0x118c5 12 altar room exit destinations 0-3 = truth (north, east, south, west), 4-7 = love, 8-11 = courage
0x118d1 146 ???
0x11963 8 ambush monster types
0x1196b 190 miscellaneous text strings
0x11a29 26 spell reagent masks (one byte per spell)
0x11a43 364 miscellaneous text strings
0x11baf 16 city/runemask pairs (city id, corresponding rune bitmask)
0x11bbf 12 miscellaneous text string
0x11bcb 120 24 five-byte item location records (see below)
0x11c43 288 ???
0x11d63 250 companion dialog text
0x11e5d 16 8 two-byte offsets to virtue adjectives for companion dialogs (value + 62123 gives file offset)
0x11e6d 1404 ???
0x11f7f 128 16 entries of 8 bytes giving the y location of different shops (?,?,?,?,?,Healer,?,?)
0x123e9 3486 Hawkwind dialog text; the first 40 zero terminated strings are his responses for 5 levels times 8 virtues, plus some other miscellaneous dialog strings
0x13187 80 40 two-byte offsets to Hawkwind dialog strings (value + 62075 gives file offset)
0x131d7 564 reagent vendor dialog text; x zero terminated strings
0x133eb 16 reagent vendor index for each city (one byte per castle/city/town)
0x133fb 8 4 two-byte offsets to reagent shop names (value + 62075 gives file offset)
0x13403 8 4 two-byte offsets to reagent shopkeeper names (value + 62075 gives file offset)
0x1340b 24 price for each of the first six reagents at Moonglow, Skara Brae, Paws, and Buccaneers Den respectively (one byte per price)
0x13423 1274 weapon vendor dialog text; 28 zero terminated strings
0x1391d 12 6 two-byte offsets to weapon shop names (value + 62075 gives file offset)
0x13929 12 6 two-byte offsets to weapon shopkeeper names (value + 62075 gives file offset)
0x13935 24 which four weapons each of the six weapons vendors can sell (one byte per weapon)
0x1394d 32 price of each weapon (two bytes for each price)
0x1396d 16 weapon vendor index for each city (one byte per castle/city/town)
0x1397d 28 14 two-byte offsets to weapon descriptions (value + 62075 gives file offset) for all weapons except hands and mystic
0x13999 522 more weapon vendor dialog text; 27 zero terminated strings
0x13ba3 646 armor vendor dialog text; 19 zero terminated strings
0x13e29 10 5 two-byte offsets to armor shop names (value + 62075 gives file offset)
0x13933 12 6 two-byte offsets to armor shopkeeper names (value + 62075 gives file offset)
0x13e3f 20 which four types of armor each of the five armor vendors can sell (one byte per armor type)
0x13e53 4 zero padding
0x13e57 16 price of each type of armor (two bytes for each price)
0x13e67 16 armor vendor index for each city (one byte per castle/city/town)
0x13e77 12 6 two-byte offsets to armor descriptions (value + 62075 gives file offset) for all armor types except skin and mystic
0x13e83 484 more armor vendor dialog text; 27 zero terminated strings
0x14067 318 horse vendor dialog text; 7 zero terminated strings
0x141a5 622 guild vendor dialog text; x zero terminated strings
0x14413 6 ???
0x14419 8 price per unit of each guild item (two bytes for each price)
0x14521 8 quantity per unit of each guild item (two bytes for each quantity)
0x14429 4 2 two-byte offsets to guild shop names (value + 62075 gives file offset)
0x1442d 4 2 two-byte offsets to guild shopkeeper names (value + 62075 gives file offset)
0x14431 8 4 two-byte offsets to guild item inquiry responses (value + 62075 gives file offset) for torches, gems, keys, sextants
0x14439 702 inn dialog text; x zero terminated strings
0x146F7 16 inn index for each city (one byte per castle/city/town)
0x14707 8 inn sleep location x coordinate for seven inns plus zero pad
0x1470f 8 inn sleep location y coordinate for seven inns plus zero pad
0x14717 8 inn prices for seven inns plus zero pad
0x1471f 14 7 two-byte offsets to inn names (value + 62067 gives file offset)
0x1472d 14 7 two-byte offsets to inn names (value + 62067 gives file offset)
0x1473b 14 7 two-byte offsets to inn price dialogs (value + 62067 gives file offset)
0x14749 424 more inn dialog text; x zero terminated strings
0x148f1 266 healer dialog text; x zero terminated strings
0x149fb 16 healer index for each city (one byte per castle/city/town)
0x14a0b 20 10 two-byte offsets to healer shopkeeper names (value + 62067 gives file offset)
0x14a1f 20 10 two-byte offsets to healer shopkeeper names (value + 62067 gives file offset)
0x14b33 598 more healer dialog text; x zero terminated strings
0x14d89 978 tavern dialog text; x zero terminated strings
0x1515b 16 tavern index for each city (one byte per castle/city/town)
0x1516b 12 minimum price for information at each tavern (two bytes for each price)
0x15177 12 6 two-byte offsets to tavern shop names (value + 62067 gives file offset)
0x15183 12 6 two-byte offsets to tavern shopkeeper names (value + 62067 gives file offset)
0x1518f 12 6 two-byte offsets to tavern specialty names (value + 62067 gives file offset)
0x1519b 12 price for plate of food at each tavern (two bytes for each price)
0x151a7 12 7 two-byte offsets to tavern information topics (value + 62067 gives file offset) (??? why 7, not 6)
0x151b5 12 6 two-byte offsets to tavern information responses (value + 62067 gives file offset)
0x151c1 598 more tavern dialog text; x zero terminated strings
0x15417 456 food vendor dialog text; x zero terminated strings
0x155df 16 food vendor index for each city (one byte per castle/city/town)
0x155ef 10 price for 25 units of food at each vendor (two bytes for each price) for Moonglow, Britan, Yew, Skara Brae, and Paws, respectively
0x155f9 10 5 two-byte offsets to food shop names (value + 62067 gives file offset)
0x15603 10 5 two-byte offsets to food shopkeeper names (value + 62067 gives file offset)
0x1560d 189 Lord British dialog keywords; 27 zero terminated strings
0x156ca 2968 Lord British dialog text; 25 zero terminated strings ("He says", plus responses for last 24 of the above keywords)
0x16262 104 ???
0x162ca 2037 Lord British "help" response dialog strings
0x16abf ... ???

Item Location Record[edit]

Each item location record has the following structure:

Offset Length (in bytes) Purpose
0x0 1 Item Location (same encoding as party location in PARTY.SAV, e.g. 0 for surface)
0x1 1 X Coordinate of Item
0x2 1 Y Coordinate of Item
0x3 2 pointer to function that handles picking up the item

External Links[edit]


Technical Details
Game Ultima IIIUltima IVUltima VUltima VIUltima VIIUltima VIIIUltima IXUltima Underworld