Ultima III Internal Formats

From Ultima Codex
Jump to: navigation, search

Note: This file was originally found here.


SHAPES.ULT[edit]

This file contains 0x50 tiles. All tiles are 16*16 pixels^2. Each tile in stored in CGA-compatible format. The first 0x20 bytes of each tile contain the first bit plane, the following 0x20 bytes contain the second bit plane.

Offset Length Purpose
0x0 0x40 tile 0x0
0x40 0x40 tile 0x1
0x80 0x40 tile 0x2
... ... ...
0x13C0 0x40 tile 0x4f


Ultima III monochrome, CGA, EGA tileset


  • The Ultima III monochrome, CGA, and EGA tileset

The index within this character set is also used to index the XP table. The table repeats every 16 monsters (with 2 rows never used), which explains why such difficult monsters like Floors or Grasses only get you a few XP. (It's not possible to actually kill Lord British or Exodus, but it's fun to see what their XP would be if you could.)

Water Merchant 1
Grass Jester 2
Brush Guard 15
Lord British 20
Fighter 8
Cleric 6
Wizard 10
Thief 5
Floor Orc 3
Chest Skeleton 4
Horse Giant 6
Daemon 8
Pincher 10
Serpent Dragon 15
Man-O-War Balron 20
Ranger Exodus 5

CHARSET.ULT[edit]

This file contains the 0x80 characters that make up the U3 font. All characters are 8*8 pixels^2. Each character in stored in CGA-compatible format. The first 0x8 bytes of each character contain the first bit plane, the following 0x8 bytes contain the second bit plane.

Offset Length Purpose
0x0 0x10 character 0x0
0x10 0x10 character 0x1
... ... ...
0x7F0 0x10 character 0x7F

SOSARIA.ULT[edit]

This file contains the world map and information about the game world state.

Offset Length Purpose
0x0 0x1000 64*64 world map
0x1000 0x180 not used
0x1180 0x20 tile number of monster 1-32; divide by 4 to get real tile number
0x11A0 0x20 tile number of floor under monster 1-32; divide by 4 to get real tile number
0x11C0 0x20 x coordinate of monster 1-32
0x11E0 0x20 y coordinate of monster 1-32
0x1200 0x20 movement flag of monster 1-32
0x1220 0x1 x coordinate of whirlpool
0x1221 0x1 y coordinate of whirlpool
0x1222 0x1 signed byte to add to x coordinate of whirlpool; possible values: 0, 1, 0xFF
0x1223 0x1 signed byte to add to y coordinate of whirlpool; possible values: 0, 1, 0xFF
0x1224 0x1 current phase of left moon; ranges from 0-7
0x1225 0x1 current phase of right moon; ranges from 0-7
0x1226 0x1 current sub-phase of left moon; ranges from 0-0xB
0x1227 0x1 current sub-phase of right moon; ranges from 0-3

Monsters, horses, ships, chests[edit]

U3 stores the location of these objects by writing them directly into the map.

Monsters[edit]

Monsters are stored as basetile_number*4. The map tile under the monster is stored in the table at 0x11A0.

Horses[edit]

Horses are stored as 0x28 == horse_tile*4. The tile under the horse can only be 0x1, because you can only dismount a horse on a grass tile.

Ships[edit]

Ships are stored as 0x2C == ship_tile*4. The tile under the ship can only be 0x0.

Chests[edit]

The map tile under the chest is encoded in the lowest 2 bits of the tile: 0x24 == chest_tile*4 + 0 --> chest on bricks (tile 0x8) 0x25 == chest_tile*4 + 1 --> chest on grass (tile 0x1) 0x26 == chest_tile*4 + 2 --> chest on forest (tile 0x2) 0x27 == chest_tile*4 + 3 --> chest on deep forest (tile 0x3) Monsters can't walk onto chests, so there can only be one chest per map square.

Moon phases and sub-phases[edit]

Each turn, both sub-phases are decremented. When a sub-phase reaches -1, it is reset to 0xB/3, and the corresponding phase is incremented. The phases are the numbers displayed on the upper border of the game world window.


DEMO.ULT[edit]

This file contains the 19*6 map displayed in the main menu. Each byte represents a tile.


MOVES.ULT[edit]

This file contains the animation script for the main menu map.

Offset Length Purpose
0x0 0x200 command table
0x200 0x200 data table


ROSTER.ULT[edit]

This file stores the infomation about all the characters the player has created.

Offset Length Purpose
0x0 0x40 character record 1
0x40 0x40 character record 2
... ... ...
0x4C0 0x40 character record 20

Character record format[edit]

NOTE: BCD = binary coded decimal (two digits per byte).

Offset Length Purpose
0x0 0xA character name; ASCII string, 0-terminated. Padded with 0's.
0xA 0x4  ?
0xE 0x1 marks and cards; bit 0-7 = love, sol, moon, death, force, fire, snake, kings
0xF 0x1 number of torches; BCD
0x10 0x1 0x0 = character is not in party, 0xFF = character is in party
0x11 0x1 status; ASCII character: G,P,D,A
0x12 0x1 strength; BCD
0x13 0x1 dexterity; BCD
0x14 0x1 intelligence; BCD
0x15 0x1 wisdom; BCD
0x16 0x1 race; ASCII character: E,D,F,H,B
0x17 0x1 class; ASCII character: W,R,T,I,A,D,F,L,C,B
0x18 0x1 gender; ASCII character: M,F,O
0x19 0x1 current magic points; BCD
0x1A 0x2 current hit points; BCD
0x1C 0x2 maximum hit points; BCD
0x1E 0x2 experience points; BCD
0x20 0x1 sub-morsels; BCD
0x21 0x2 food; BCD
0x23 0x2 gold; BCD
0x25 0x1 gems; BCD
0x26 0x1 keys; BCD
0x27 0x1 powders; BCD
0x28 0x1 currently worn armor
0x29 0x7 how many of each armor type; BCD
0x30 0x1 currently readied weapon
0x31 0xF how many of each weapon type; BCD

Sub-morsels[edit]

This field contains 2 digits (those behind the decimal point) of the food field. On the surface, the game subtracts 10 from this field during every turn (remember that it contains a BCD). Everywhere else, the game subtracts 10 every 4 turns.

Weapon types[edit]

Offset Letter Name
0x31 B Dagger
0x32 C Mace
0x33 D Sling
0x34 E Axe
0x35 F Bow
0x36 G Sword
0x37 H 2H Sword
0x38 I +2 Axe
0x39 J +2 Bow
0x3A K +2 Sword
0x3B L Gloves
0x3C M +4 Axe
0x3D N +4 Bow
0x3E O +4 Sword
0x3F P Exotic Weapon

Armor types[edit]

Offset Letter Name
0x29 B Cloth
0x2A C Leather
0x2B D Chain
0x2C E Plate
0x2D F +2 Chain
0x2E G +2 Plate
0x2F H Exotic Armor


PARTY.ULT[edit]

This file contains information about the current party. BCD = binary coded decimal (two digits per byte).

Offset Length Purpose
0x0 0x1 mode of transportation; 0xA = horse, 0xB = ship, 0x3F = on foot
0x1 0x1  ?
0x2 0x1 party location
0x3 0x4 number of moves; BCD
0x7 0x1 number of characters in the party
0x8 0x1 x coordinate of party (on Sosarian map)
0x9 0x1 y coordinate of party (on Sosarian map)
0xA 0x4 number of PC in slot 1-4 (party order)
0xE 0x4  ?
0x12 0x40 character record for PC 1
0x52 0x40 character record for PC 2
0x92 0x40 character record for PC 3
0xD2 0x40 character record for PC 4

Party location[edit]

Value Location
0 Sosaria
1 dungeon
2 towne
3 castle (LB's Castle, Castle Death)
4 shrine, fountain, mark
0x80 combat
0xF0 talking to merchant
0xFF Ambrosia

Note: You can only save your game in Sosaria, so the party location field in the file is always 0.


.ULT files (town maps)[edit]

These files contain the map and "dialog" for each town. There are 32 NPC's in every town. (?)

BRITISH.ULT Lord British's castle
DAWN.ULT Dawn
DEATH.ULT Death Gulch
DEVIL.ULT Devil Guard
EXODUS.ULT Exodus (Castle Death)
FAWN.ULT Fawn
GREY.ULT Grey
LCB.ULT Britain
MONTOR_E.ULT Montor East
MONTOR_W.ULT Montor West
MOON.ULT Moon
YEW.ULT Yew

Map format[edit]

Offset Length Purpose
0x0 0x1000 64*64 town map
0x1000 n*0x2 sign text offsets; n <= 8, add 0x1000 to get the real offset
0x1000+n*0x2 variable sign texts and dialog; all texts are 0-terminated ASCII strings
0x1180 0x20 tile number for each NPC; divide by 4 to get real tile number
0x11A0 0x20 tile number of floor under each NPC; divide by 4 to get real tile number
0x11C0 0x20 starting x coordinate of each NPC
0x11E0 0x20 starting y coordinate of each NPC
0x1200 0x20 movement flag + dialog number
0x1220 0x8 not used

Movement flag + dialog number[edit]

(byte >> 4) == 0 --> NPC walks around

(byte >> 4) == 4 --> NPC doesn't move

(byte >> 4) == 8 --> NPC is a merchant

(byte >> 4) == 0xC --> NPC attacks party

(byte % 0xF) == sentence number

Still unknown: 0x85, 0x86 (?)

.ULT files (dungeon maps)[edit]

These files contain the dungeon maps and sign texts.

DARDIN.ULT Dardin's Pit
FIRE.ULT Dungeon of Fire
M.ULT Dungeon of Doom
MINE.ULT Mines of Morinia
P.ULT Dungeon of the Snake
PERINIAN.ULT Perinian Depths
TIME.ULT Dungeon of Time

Map format[edit]

Offset Length Purpose
0x0 0x100 16*16 map of level 1
0x100 0x100 16*16 map of level 2
... ... ...
0x700 0x100 16*16 map of level 8
0x800 n*0x2 sign text offsets; n = 8, add 0x800 to get the real offset
0x810 0x80 sign texts; every sign text is a null-terminated ASCII string

There is at most one sign per dungeon level. To find out the text for a sign, use (dungeon_level-1) as an index into the table at 0x800.


.ULT files (conflict maps)[edit]

These files contain the 11*11 conflict maps.

CNFLCT_A.ULT

CNFLCT_B.ULT

CNFLCT_C.ULT

CNFLCT_F.ULT

CNFLCT_G.ULT grasslands

CNFLCT_M.ULT

CNFLCT_Q.ULT

CNFLCT_R.ULT

CNFLCT_S.ULT

Map format[edit]

Offset Length Purpose
0x0 0x79 11*11 map; each byte represents one tile
0x79 0x7  ?
0x80 0x8 starting x coordinates for monsters 1-8
0x88 0x8 starting y coordinates for monsters 1-8
0x90 0x8 not used
0x98 0x8 not used
0xA0 0x4 starting x coordinates for PC's 1-4
0xA4 0x4 starting y coordinates for PC's 1-4
0xA8 0x4 not used
0xAC 0x4 not used

U3 uses the 8 bytes at offset 0x90 (in memory) to store the tiles under monster 1-8. U3 uses the 8 bytes at offset 0x98 (in memory) to store the hit points of monster 1-8. U3 uses the 4 bytes at offset 0xA8 (in memory) to store the tiles under PC 1-4. U3 uses the 4 bytes at offset 0xAC (in memory) to store the base tiles for PC 1-4. U3 doesn't use the values stored at these locations in the conflict files.

.IMG files[edit]

Each of these files contains an 11*11 tile image. Each byte represents a tile number.

BRAND.IMG Brand
FOUNTAIN.IMG Fountain
SHRINE.IMG Ambrosian shrine
TIME.IMG Time Lord

Further Notes[edit]

I'm pretty sure that U3 doesn't save the wind direction.


External Links[edit]


Technical Details
Game Ultima III Ultima IV Ultima V Ultima VI Ultima VII Ultima VIII Ultima IX Ultima Underworld Series