Ultima IV internal formats
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 :
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:
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 III ☥ Ultima IV ☥ Ultima V ☥ Ultima VI ☥ Ultima VII ☥ Ultima VIII ☥ Ultima IX ☥ Ultima Underworld |