/
uw-formats.txt
4762 lines (3817 loc) · 180 KB
/
uw-formats.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
+--------------------------------------------------------------------------+
Ultima Underworld 1 and 2 Formats Specification
Underworld Adventures
https://vividos.github.io/UnderworldAdventures/
+--------------------------------------------------------------------------+
Document version: 1.86, as of 2023-08-09
Table of Contents
-----------------
1 Introduction
2 Overview
2.1 Remarks
2.2 Document conventions
2.3 Summary of game files
2.3.1 Ultima Underworld 1 files
2.3.2 Ultima Underworld 2 files
3 Graphics and visuals
3.1 Palettes
3.2 Images
3.3 Bitmaps
3.4 Textures
3.5 Fonts
3.6.1 Critter animations [uw1]
3.6.2 Critter animations [uw2]
3.7.1 Cutscene animation [uw1]
3.7.2 Cutscene animation [uw2]
3.8 Weapon animations
3.9 XFER.DAT Transparencies
3.10 Lights/Shading
3.10.1 List of all lights
3.10.2 UW2 level light
4 Level maps and object lists
4.1 File format
4.2 Level tilemap
4.3 Object list
4.3.1 Enchantments
4.3.2 Item Owner
4.3.3 Mobile object extra info
4.4 Free lists
4.5 Texture mappings
4.6 Animation infos
4.7 Automap infos
4.8 Map notes
4.9 Terrain texture properties
5 String resources
5.1 String block contents [uw1]
5.2 String block contents [uw2]
6 Objects and items
6.1 List of all objects and items
6.2 Common object properties
6.3 Object class properties
6.4 Object combining
7 Conversations
7.1 Conversation file format
7.2 Private global variables
7.3 Memory layout
7.4 Assembler language opcodes
7.5 Text substitutions
7.6 Intrinsic functions
7.6.1 Ultima Underworld 1 intrinsic functions
7.6.2 Ultima Underworld 2 intrinsic functions
7.7 Imported variables
7.8 Quest flags
8 3D models
8.1 List of all nodes
9 Miscellaneous stuff
9.1 Ultima Underworld 2 compression scheme
9.2.1 Savegame format [uw1]
9.2.2 Savegame Format [uw2]
9.3 Unknown files
9.4 Error codes
10 Sound
10.1 sounds.dat
10.1.1 sounds.dat [uw2]
10.1.2 sounds.dat [uw2]
10.2 VOC files [uw2]
10.3 XMI files
+--------------------------------------------------------------------------+
1 Introduction
This file tries to collect all file formats and data structures used in the
game Ultima Underworld 1. It originated from the "uw-specs.txt" file that I
found with "The System Shock Hack Project" (TSSHP). System Shock uses
almost the same data structures for the game and Jim decided to support the
underworldly games, too. With the start of the Underworld Adventures
project I started to extend the file as I found new things. It started with
a tiny 20kb text file.
As I further progressed to find out things I realized that the Underworld
games are not that simple done as I always thought. Many little things want
to be specified, configured and set. The Underworld games were built very
detailed, far more than other games at this time. The second game even
added to that complexity (and some say, story, too).
With this document I hope to present the interested reader a rather
detailed overview over the file formats, and even more the inner workings
of Ultima Underworld 1 and 2. Have as much fun reading it as I had fun to
find out things and writing it!
1.1 Credits
My thanks go out to Jim Cameron that started the original "uw-specs.txt"
file and subsequently found out more unknown data structures and discussed
about file formats with me. Many thanks, Jim!
Additional information came from:
- Alistair Brown (basic object format, via the Underworld II editor
available at http://bearcity.pwp.blueyonder.co.uk/)
- Ulf Wohlers (Objects and 3D models)
- Fabian Pache (about map details and 3D models, uw2 conversations uw2
player save http://uw2rev.sourceforge.net)
- Hank Morgan, from his UnderworldExporter project
https://github.com/hankmorgan/UnderworldExporter
- Marc A. Pelletier (coren), from the Labyrinth of Worlds project
(http://low.sourceforge.net/)
- Telemachos (http://www.peroxide.dk/), infos about weapon animation and
miscellaneous bits about uw.
- Murgo (https://web.archive.org/web/20090119003115/http://uwediting.freehostia.com:80/files/uwcspecs.txt),
various infos
I also like to thank Telemachos who pointed me to the TSSHP's file formats
file at the start of all of this.
This file is probably:
Copyright (c) 2014-2018 Hank Morgan
Copyright (c) 2008,2009 Julien Langer
Copyright (c) 2002,2008,2009 Fabian Pache
Copyright (c) 2000,2001,2002,2003 Jim Cameron
Copyright (c) 2002,2003,2004 Michael Fink
Copyright (c) 2004 Kasper Fauerby
Copyright (c) 2022 Mike Ratzlaff
Copyright (c) 2008 Murgo
+--------------------------------------------------------------------------+
2 Overview
This chapter gives a short overview over the game itself, as well as a
detailed summary about all game files used in Ultima Underworld 1 and 2.
2.1 Remarks
The game was released in the year 1992, just before Wolfenstein 3D came
out.was released. So it was the first true first-person game on the PC.
Ultima Underworld is a MS-DOS based game created in C with Turbo C++ 2.1
and Optasm as the assembler used (as far as we know). 3D models were done
with 3D Studio Max and converted and placed into the executable.
Ultima Underworld is a trademark of Origin, Inc.
2.2 Document conventions
This document follows some conventions, to keep a nice and well-to-read
format. The document is indented by 3 spaces; text must be wrapped at
line column 79 and tables can (but doesn't need to be) indented with 3
spaces, too. No tab spaces should be used. Special parts of the formats
specification that only refer to either Ultima Underworld 1 or 2 are marked
with [uw1] or [uw2].
All integer data values in the documentation are referred as Int8 for 8-bit
values, Int16 and Int32 for 16-bit and 32-bit values. All values are
unsigned unless noted otherwise. As the game was written and run on x86 PC
machines, all variables are stored in little-endian format, where e.g. the
lower byte of a 16-bit value is stored first, then the higher byte. All
data structures found so far use this scheme.
2.3 Summary of game files
This section lists all the files that are part of the Ultima Underworld
game installations.
2.3.1 Ultima Underworld 1 files
Here's a list of all files for Ultima Underworld 1:
Files in the main folder:
install.dat infos which files are installed
install.exe installer created with EZ-INSTALL 3.13
install.olb ANSI text strings for the installer
lha.doc LHA manual for 2.13
lha.exe LHA 2.13 to unpack installer game files
uw.exe ultima underworld 1 executable
uwsound.exe sound settings program
Files in the "data" folder:
3dwin.gr 3d window graphics
allpals.dat auxiliary 4-bit palette indices
animo.gr small animations
armor_f.gr female paperdoll armor graphics
armor_m.gr male paperdoll armor graphics
babglobs.dat initial conversation globals
blnkmap.byt blank map bitmap, palette #1
bodies.gr paperdoll bodies
buttons.gr buttons, seems to be from some map editor
chains.gr rotating chains for the stats window
chargen.byt character generation bitmap, palette #3
charhead.gr character images, for conversations
chrbtns.gr character generation graphics, palette #3
chrgen.dat character generation data?
cmb.dat item combining rules
cnv.ark conversation scripts
comobj.dat common object properties
compass.gr compass graphics
conv.byt seems to be a conversation screenshot, palette #0
converse.gr conversation screen bitmaps
cursors.gr mouse cursor images (uw1 palette #0, uw2 palette #?)
doors.gr door textures
dragons.gr scroll dragons animations
eyes.gr eyes from top screen
f16.tr floor/ceiling textures, size 16x16
f32.tr floor/ceiling textures, size 32x32
flasks.gr health and mana flask graphics
font4x5p.sys small font
font5x6i.sys italic font, used in character stats screen
font5x6p.sys normal font, used for scroll messages
fontbig.sys big font, for cutscenes
fontbutn.sys font for buttons (?)
fontchar.sys character generation font (?)
genhead.gr generic heads images
grave.dat grave IDs
heads.gr avatar character generation heads
inv.gr inventory graphics, scroll backgrounds (?)
lev.ark level maps, texture indices and object list
lfti.gr left menu buttons
light.dat palette mappings for 16 different light levels
lights.dat
main.byt main game screen bitmap, palette #0
mono.dat palette mapping for grayscale colors
objects.dat object data specific to an object class
objects.gr object graphics, some never seen in inventory (460 objects!)
opbtn.gr opening screen buttons, create new game, etc.; palette #2
opscr.byt opening screen, palette #2
optb.gr some options buttons
optbtns.gr all options buttons from the left menu
pals.dat eight palettes (#0 to #7; #5 and #6 are the same)
panels.gr some invalid type, 0x0 and 1x1 resolution images
player.dat initial player character called "gronkey"
power.gr hit power indicator graphics
pres1.byt "origin presents" screen, palette #5
pres2.byt "a blue sky prod. game" screen, palette #5
question.gr a single question mark
scrledge.gr scroll paper edges
shades.dat light infos
skills.dat char. generation skills for all classes
spells.gr spells graphics
strings.pak all the game strings
terrain.dat terrain texture properties (see 4.7)
tmflat.gr wall switches and other decals
tmobj.gr more wall decals, 3d model textures
uw.cfg underworld configuration (audio, cut scenes)
views.gr the letters "mv", probably not used
w16.tr wall textures, size 16x16
w64.tr wall textures, size 64x64
weapons.cm weapon animation auxiliary palettes (see 3.8)
weapons.dat weapon animation x and y coordinates (see 3.8)
weapons.gr weapon hit animations, for left and right handedness
win1.byt winning screen with text, palette #7
win2.byt blank winning screen for character info, palette #7
xfer.dat color index translation tables (see 9.3)
Files in the "sound" folder:
XX.voc all cutscene audio files
uwXX.xmi underworld extended midi music
awXX.xmi the same, for adlib music (?)
sounds.dat sound effect midi commands
uw.mt MT32 timbre library
uw.ad adlib timbre library
*.adv device driver for midi/wave output:
adlib.adv Ad Lib Music Synthesizer Card
mt32mpu.adv Roland MT-32 or compatible
pasdig.adv Pro Audio Spectrum Digital Sound
pasfm.adv Pro Audio Spectrum FM Sound
pcspkr.adv IBM PC or compatible internal speaker
sbdig.adv Sound Blaster Digital Sound
sbfm.adv Sound Blaster FM Sound
sbpdig.adv Sound Blaster Pro Digital Sound
sbpfm.adv Sound Blaster Pro FM Sound
tandy.adv Tandy 3-voice internal sound
Here's a list of song names for the .xmi files:
uw01.xmi Introduction
uw02.xmi Dark Abyss
uw03.xmi Descent
uw04.xmi Wanderer
uw05.xmi Battlefield
uw06.xmi Combat
uw07.xmi Injured
uw10.xmi Armed
uw11.xmi Victory
uw12.xmi Death
uw13.xmi Fleeing
uw15.xmi Maps & Legends
Files in the "cuts" folder:
* = not in "static" install
cs???.n00 cutscene control files
cs000.n01 black screen
cs000.n02 * garamon in swirling air
cs000.n03 garamon talking
cs000.n04 * garamon talking
cs000.n05 * garamon talking
cs000.n06 * garamon in swirling air
cs000.n07 garamon appearing
cs000.n10 intro w/ tyball stealing princess, troll and guards etc.
cs000.n11 almric talking, on throne
cs000.n12 almric talking, closeup
cs000.n15 guard talking
cs000.n16 * guard talking
cs000.n17 * guard talking
cs000.n20 mountain scene, avatar taken to the abyss
cs000.n21 * mountain scene
cs000.n22 abyss doors closed, from outside
cs000.n23 doors closed, from inside, w/ avatar
cs000.n24 guard talking, with purple background
cs000.n25 * guard talking, with purple background
cs001.n01 ship approaching, abyss collapsing
cs001.n02 ship taking avatar on board
cs001.n03 almric talking, on ship
cs001.n04 almric talking, on ship
cs001.n05 * almric talking, on ship, birds in background
cs001.n06 arial talking
cs001.n07 arial talking
cs001.n10 abyss collapsing, ship sails away
cs002.n01 dying tyball talking
cs002.n02 * dying tyball talking
cs002.n03 * dying tyball talking
cs002.n04 * dying tyball, dying
cs003.n01 arial talking
cs003.n02 * arial talking
cs011.n01 "ultima underworld the stygian abyss" splash screen anim
cs012.n01 acknowledgements
cs013.n01 goblet with letters "in"
cs014.n01 goblet with letters "sa"
cs015.n01 goblet with letters "hn"
cs400.n01 "look" graphics for windows to abyss volcano core
cs401.n01 grave stones
cs402.n01 death skulls w/ silver sapling
cs403.n01 death skulls animation
cs403.n02 death skull end anim
cs404.n01 anvil graphics
cs410.n01 map piece showing some traps
Files in the "crit" folder:
assoc.anm animation associations
Files in a save game folder (e.g. "Save1"):
lev.ark modified level map
bglobals.dat conversation globals (initialized)
desc savegame name
player.dat character info
Files that only appear in the uw_demo "data" folder:
df??.tr floor textures
dmain.byt main screen
dplayer.??? encrypted player character info for self-running demo
dscript.??? scripts for self-running demo sequences
dterrain.dat terrain texture properties for the demo
dw??.tr wall textures
level13.anx object animation overlay info
level13.st tilemap and object list for first level
level13.txm level texture usage for first level
newobj.dat
presd.byt "... presents a demo of ..." screen for the demo
2.3.2 Ultima Underworld 2 files
Here is a list of all files from Ultima Underworld 2 that differ in content
or are only available in the second game.
Files in the main folder:
uinstall.exe game installer (LZEXE 0.91 compressed)
uw2.exe Ultima Underworld 2 game
Files in the "data" folder:
byt.ark game bitmaps archive
cnv.ark compressed conversation archive
dl.dat
gempt.gr red gem parts (?)
ghed.gr
lev.ark compressed levelmap archive
lighting.dat
pals.dat 11 palettes
scd.ark NPC schedules?
weap.cm weapon animation auxiliary palettes (see 3.8)
weap.dat weapon animation x and y coordinates (see 3.8)
Files in the "cuts" folder:
cs000.n?? intro part 1: letter to the avatar
cs001.n?? intro part 2: blackrock shell
cs002.n?? outro
cs004.n?? audio only cutscene ?
cs005.n?? audio only cutscene ?
cs006.n?? audio only cutscene ?
cs007.n?? audio only cutscene ?
cs011.n?? title screen, "ultima underworld 2, labyrinth of worlds"
cs012.n?? credits
cs030.n?? blue vision
cs031.n?? blue vision
cs032.n?? blue vision
cs033.n?? blue vision
cs034.n?? guardian on red
cs035.n?? guardian on camo
cs036.n?? guardian on blue
cs037.n?? guardian on green
cs040.n?? guardian on black
cs403.n?? player death, bubbling skulls
lback00?.byt large background files for camera paning cutscenes (0..8)
Files in the "crit" folder:
as.an animation associations
cr.an animation segment list
pg.mp page file
crXX.YY critter animations, XX=animation(octal) YY=page
Files in the "sound" folder:
bsp??.voc guardian speech
dd??.adv digital sound drivers
dm??.adv digital music drivers
sample.opl
sp??.voc sound effects
uw.opl OPL timbre library
uw??.voc guardian laughter
uwa??.xmi adlib music files
uwr??.xmi roland music files
Here's a list of song names for the .xmi files:
uwa01.xmi The Labyrinth of Worlds Theme
uwa02.xmi Enemy wounded
uwa03.xmi Combat
uwa04.xmi Dangerous Situation
uwa05.xmi Armed
uwa06.xmi Victory
uwa07.xmi Sewers
uwa10.xmi Talorus, Ethereal Void
uwa11.xmi Prison Tower
uwa12.xmi Death
uwa13.xmi Killorn Keep, Pits of Carnage
uwa14.xmi Ice Caverns
uwa15.xmi Scintillus Academy
uwa16.xmi Praecor Loth, Castle British
uwa17.xmi The Labyrinth of Worlds Theme (again)
uwa30.xmi Introduction
uwa31.xmi Guardian's Trap
Some variations of the names come from some mp3 files available here:
http://stygian.ttlg.mobi/uw/music/uw2.htm
+--------------------------------------------------------------------------+
3 Graphics and visuals
This chapter explains all visual formats used, e.g. wall/floor/ceiling
textures, user interface images or animations.
3.1 Palettes
Ultima Underworld uses several palettes for different purposes. There are
palettes with 256 indices, as well as auxiliary meta-palettes that have
16 or 32 entries that map indices to the 256-index palette. As the original
games directly load the palettes into the VGA registers, effects as color
flashes done with palette rotating are possible.
3.1.1 256 color palettes
In the file "pals.dat" there are stored 8 different palettes in UW1 and
11 in UW2. A palette has the following layout:
0000 Int8 red intensity, index 0, range [0..63]
0001 Int8 green intensity, index 0, range [0..63]
0002 Int8 blue intensity, index 0, range [0..63]
0003 Int8 red intensity, index 1, range [0..63]
0004 Int8 green intensity, index 1, range [0..63]
...
02fe Int8 green intensity, index 255, range [0..63]
02ff Int8 blue intensity, index 255, range [0..63]
In each palette there are stored color intensities for 256 colors. All
palettes are stored sequentially in the file.
Palette index 0 always means transparent color.
3.1.2 16 color auxiliary palette mappings
In "allpals.dat" there are several auxiliary palettes, used for 4-bit
images. All indices use palette #0.
0000 Int8 index to first color
0001 Int8 index to second color
...
000f Int8 index to 16th color
There are 16 values that are indices for palette #0. They build a 16 color
palette from selected colors of the palette #0.
In the file "allpals.dat" there are stored 0x1f (=31) such palettes.
The critter animations (explained in chapter 3.6) use 32 color auxiliary
palette mappings. They are stored within the animation files.
3.1.3 Palette mappings
Palette mappings for different light/darkness levels are stored in the
file "light.dat". The file consists of 16 blocks of palette mappings. Each
block contains 256 Int8 values which map colors to their palette indices in
the game palette. The first block is the mapping for original colors, and
the last one is for "almost black".
The file "mono.dat" contains palette mappings that maps colors to grayscale
values. It has the same format as the "light.dat" file and can be
interchanged to get a gray underworld look. It is used for the spell
"invisibility".
3.1.4 Palette rotation animations
In several places of the game the palette is used to create animated
effects, such as the lava and water textures. Here are the palette indices
that have to be rotated to produce the animations:
- Palette #0: in game graphics
[UW1]
indices 16 through 23: lava fire effect
These 8 indices are rotated for fire/lava effect, but are not all rotated
together. The first 5 are rotated together, and the next 3 are rotated
together. These rotations move "up", as in the colors "travel" up the
palette from lower indices to higher.
indices 48 through 63: water effect
These 16 indices are rotated for water effects, however the group of 16
colors are not all rotated together. They are broken up into 4 groups of 4,
and those groups are each rotated individually. These rotations move colors
"down" from higher indices to lower ones.
[UW2]
Uses the same rules stated above, but palette indices are different:
indices 3 through 10: lava fire effect
indices 224 through 239: water effect
- Palette #2: game start screen
indices 64 through 127: "Ultima Underworld" logo warping effect [uw1]
indices 43 through 48, 49 through 51, 57 through 66: "Labyrinth of Worlds"
logo blinking effect [uw2]
3.2 Images
Graphics are stored in "*.gr" files and can be stored with 8-bit or 4-bit
indices.
0000 Int8 Graphic file format:
01 .gr
02 .tr
03 .cr [uw2]
04 .sr [uw2]
05 .ar [uw2]
0001 Int16 number of bitmaps
0003 Int32 offset to bitmap #0
0007 Int32 offset to bitmap #1
...
Entries in .gr files can contain null records. There will be a place-holder
entry in the offsets table, but it does not point to a valid graphics record
for that entry. A record should be considered null if:
The offset points past the end of file or
The offset is the same as the next offset in the list
If you are ripping graphics from .gr files and notice duplicate graphics,
such as the blood splats and damage traps in objects.gr, then you have not
properly accounted for null records.
Each bitmap has its own header:
0000 Int8 bitmap type:
04: 8-bit uncompressed
08: 4-bit run-length
0A: 4-bit uncompressed
0001 Int8 width
0002 Int8 height
For the 4-bit formats, there follows another Int8 that selects the
auxiliary palette to use (see 2.1).
000n Int16 size of data for the bitmap.
For bitmap type 08, this is the number of 4-bit nibbles, not
bytes. Actual byte count is nibbles/2 rounded up.
For bitmap types 04 & 0A, this is the actual byte count.
The file "panels.gr" contains bitmaps that don't have a bitmap header, but
immediately start with image data. There are 4 bitmaps of type 04 that have
a hard-coded height and width.
[UW1] The first three are 83 x 114 and the final one is 3 x 120
[UW2] The first three are 79 x 112 and the final one is 3 x 112
3.2.1 Uncompressed bitmaps (04: 8-bit, 0A: 4-bit)
All palette indices are stored sequentially, first one line, then the
next, and so on. For the 4-bit format, first take the upper nibble, then
the lower nibble.
3.2.2 Compressed bitmaps (type 08, type 06)
Compressed bitmaps are stored with a run length encoding and a
lookup table. The wordsize used for a certain bitmap is determined by the
type.
type 08: wordsize 04 bits
type 06: wordsize 05 bits
If the size of the compressed image is given in words, the number of bytes
are calculated as
bytecount = (wordcount * wordsize + 7) / 8
The bytes of the compressed image are treated as a bit stream, starting
at the most significant bit of byte 0.
Data consists of repeat and run records.
- Repeat records let the decoder repeat a single word a certain number
of times.
- Run record takes a certain number of next nibbles to be as
uncompressed.
The decompression engine keeps a counter of the number of repeat records
that precede the next run record. This counter is initially 1. See
special count interpretation for repeat records below.
For every record, first there is a count to retrieve. A count is a single
number made up from a variable number of words. The algorithm to determine
a count is as follows:
Get a word.
c = w0
If it is not 0, it is a count. Otherwise, get two more words,
w1 and w2. The count is:
c = (w1 << 4) | w2
If the count is still zero, take another three words, and calculate the
count:
c = (((w3 << 4) | w4) << 4) | w5
Note that even if the wordsize is 5, the words are only shifted by 4 bits,
thus overlapping the words theoretically. In practice a count is at most 6
words long, leading to the following possible patterns:
1 word count : [w0] , with (w0) != 0
2 word count : 0 [w1] [w2] , with (w1 << 4 | w2) != 0
3 word count : 0 0 0 [w3] [w4] [w5]
A run record consists of a count and then follow 'count' words, that are
the raw pixel data. A repeat record consists of a count and a single word,
the nibble is then repeated 'count' times.
As there is no point in repeating a nibble <3 times, there are some
special meanings for count:
1: skip this record, the next one is a run record again. May be used at
the beginning of a file, when it should start with a run rather than
a repeat.
2: multiple repeats. Get another count, and process 'count' times a
repeat record.
Note that there are cases where the decompression yields a greater number
of words than would be necessary to display the image.
The resulting words make up the atom map for a given image. This atom map
is then translated, byte by byte, from their value range of 16 (4 bit) or
32 (5 bit) to full 8 bit using the corresponding atom to fragment maps.
These maps are also sometimes referred to a auxiliary palettes in this
document.
3.3 Bitmaps
Bitmaps in Ultima Underworld 1 are stored in "*.byt" files. They just are
320x200 bitmaps using different palettes. Here's a list of all bitmap
files:
blnkmap.byt blank map bitmap, palette #1
chargen.byt character generation bitmap, palette #3
conv.byt seems to be a conversation screenshot, palette #0
main.byt main game screen bitmap, palette #0
opscr.byt opening screen, palette #2
pres1.byt "origin presents" screen, palette #5
pres2.byt "a blue sky prod. game" screen, palette #5
win1.byt winning screen with text, palette #7
win2.byt blank winning screen for character info, palette #7
Ultima Underworld demo contains two separate bitmaps:
dmain.byt main demo screen bitmap, palette #0
presd.byt "origin and blue sky prod. present..." screen, palette #5
Underworld 2 has no "*.byt" files. Instead there is one "byt.ark" that
contains all images. Like every other "*.ark" file this starts with some
tables followed by the data, in this case the images themselves. There are
11 entries, of which only 9 are valid:
entry palette usage
0 1 Map framework - background, crystal, and the like
1 0 Character generation
2 0 Bartering
3 -unused-
4 0 HUD - the frame, bottles, scroll
5 0 Underworld 2 Main menu - without menu entries
6 5 Origin presents
7 5 Looking Glass Technologies
8 0 Congratulation screen
9 0 like the above but without the text
10 -unused-
3.4 Textures
Textures are stored in "*.tr" files, where "fXX.tr" files are floor/ceiling
textures, and "wXX.tr" are wall textures. XX describes the width and height
resolution of the texture (textures are always square).
0000 Int8 graphic file format; always 2
0001 Int8 x and y resolution
0002 Int16 number of textures in file
0004 Int32 offset to texture #0
0008 Int32 offset to texture #1
...
The offset of each texture points to the actual texture palette indices,
which are xyres^2 bytes long. Textures always use palette #0.
Texture names are stored in string block 10, where wall textures start at
position 0, and floor textures start at 510, going backwards. The string
at position 511 is reserved for the ceiling.
3.5 Fonts
Fonts are stored in "font*.sys" files, and can be non-proportional (chars
can have different lengths). The header looks as this:
0000 Int16 unknown, always 1 (might be size of character width field)
0002 Int16 size of single character, in bytes (=charsize)
0004 Int16 width of the blank (space) character, in pixels
0006 Int16 font height in pixels
0008 Int16 width of a character row in bytes
000A Int16 maximum width of a character in pixels (=maxwidth)
Then follow all bitmaps for each character. The number of chars can be
determined by (filelen-12) / (charsize+1). Bitmaps are stored as 1-bit
patterns, starting at the most significant bit in the current byte. When
a new line in character bitmap begins, remaining bits are unused and a new
byte in the file is taken.
After 'charsize' number of bytes, there is another Int8 that says the width
for the current character in pixels.
Note: at least the fonts "fontbig.sys" and "font5x6p.sys" contain overly
large characters, and for these the remaining bits at a line are used. The
maxwidth field should be corrected for loading.
3.6.1 Critter animations [uw1]
Critter animations are stored in the folder "crit". The file "assoc.anm"
holds data for each of the 32 animations and for the 64 NPC types. The file
starts with 8 bytes for the name of each animation. Shorter strings are
padded with zeros. Empty strings denote animations not available (e.g. in
the "uw_demo").
Next comes a table of infos for each NPC. The table is 64 entries (0x0080)
long:
0000 Int8 anim
0001 Int8 auxpal
The "anim" field specifies which one of the 32 animations to take for a
given NPC number (NPC object ID - 0x0040). A value of 0xff indicates that
no animation is available.
The "auxpal" value describes which auxiliary palette to use. There are
several critters that share the same animations but use different palettes,
e.g. the bat and the vampire bat uses the same anim value, but different
auxiliary palettes.
Animation for each critter is stored in a file named "crXXpage.nYY", where
XX = animation number (=anim), YY = page number
XX and YY are octal numbers
There may be more than one page for each animation file.
The file starts with a header:
pos length desc.
0000 Int8 anim slot base
0001 Int8 number of anim slots (=nslot)
0002 nslot*Int8 list of segment indices
After this, a list of segment follows which contains up to 8 frame indices
for every segment.
nslot+2 Int8 number of anim segments (=nsegs)
8*nsegs anim frame indices
Then the auxiliary palettes follow:
Int8 number of aux palettes (=npals)
npals*32 allaux palette indices in blocks of 32
Next is a list of all frames and their offsets into the file:
Int8 number of frame offsets (=noffsets)
Int8 compression type? (always 06)
noffsets*Int16 absolute offsets to frame headers
Each animation is stored in a segment which can contain a number of
frames (stored in the "animation frame indices"). Each list is padded with
0xFF entries.
frame header
0000 Int8 width
0001 Int8 height
0002 Int8 hotspot x
0003 Int8 hotspot y
0004 Int8 compression type; (06: 5-bit word size)
0005 Int16 data length in number of words
0007 start of rle-encoded image data (see 2.3)
The hotspot coordinates are to "pin" the image at a specific position. The
hotspot coordinates in the image should always be on the same place when
rendered. The compression type can be 06, which is 5-bit run-length
encoding, or 08, which is 4-bit run-length encoding (see 2.3. for more).
The slot lists group together segments of animations for various actions.
Here's a list of slots and their actions:
slot action
00 combat idle
01 attack, bash (?)
02 attack, slash (?)
03 attack, thrust
05 second weapon attack
07 walking / running towards player
0c death
0d ??
20 idle, facing away from player (180 degrees)
21 idle, 135 deg.
22 idle, angle 90 deg.
23 idle, angle 45 deg.
24 idle, facing towards player, 0 deg.
25 idle, angle -45 deg.
26 idle, angle -90 deg.
27 idle, angle -135 deg.
Segment indices at 80-87 are the same as above, except that these are the
walking animations. For the animations used in the Ethereal Void (level 9)
the slot list is somewhat different.
Here is a list of animation files and their contents:
file assoc name auxpals used in
cr00 * "gngob32" 4 green goblin
cr01 "skela" 1 skeleton
cr02 "lizman" 3 green, red and gray lizardman
cr03 * "bat" 3 cave bat, vampire bat
cr04 "wiza" 5 yellow male mage
cr05 * "spider" 3 giant, wolf, dread spider
cr06 "gazer" 1 gazer
cr07 "troll" 3 troll, feral troll, great troll
cr10 "femwiz" 4 female mage
cr11 * "slug" 2 flesh slug, acid slug
cr12 "fire" 2 fire elemental
cr13 "ghoul" 3 ghoul, dark ghoul
cr14 "demon" 1 Slasher of Veils
cr15 * "ghost" 4 ghost, dire ghost
cr16 * "graygob" 2 gray goblin
cr17 "reaper" 1 reaper
cr20 * "rat" 2 giant rat
cr21 "femfite" 3 female fighter
cr22 * "imp" 2 imp, mongbat
cr23 "golem" 3 earth, stone and metal golem
cr24 * "hedless" 1 headless
cr25 "wizb" 3 blue female mage
cr26 * "rotgrub" 2 green rotworm, bloodworm
cr27 "wisp" 1 wisp
cr30 "batskull" 2 bat, teeth, vortex, hound (level 9)
cr31 * "Lurk" 2 lurker, deep lurker
cr32 * "fight32" 4 male fighter, outcast, adventurer
cr33 "dwarf32" 3 mountainman
cr34 "shadow" 2 shadow beast
cr35 "tybal" 1 tyball
cr36 "eye" 1 eye, skull (level 9)
cr37 "litening" 1 lightning, fish (level 9)
The animations marked with * are available in the uw_demo, too.
3.6.2 Critter animations [uw2]
The following files of the CRIT folder are involved in Underworld 2
animations:
pg.mp contains a skiptable to find a frame in the crXX.YY files
cr.an animation sequences for all critter and all actions
as.an contains a mapping of critter IDs to crXX.YY files and palettes
crXX.YY the pixel information for critter XX, fragment YY
XX and YY are using octal digits
The "pg.mp" file has a map of all crXX.YY files and how many frames are
found in each file.
The "as.an" file is like the "assoc.anm" file from uw1, but without the
animation name string table at the start; it is 128 bytes long. It maps
from actual critter item IDs (0x0040-0x007f, 128) to 32 critter animations,
and which auxiliary palette to use for each.
The "cr.an" file specifies, for each of the 32 critter animation types, the
frames needed to render for 8 different animations and 8 viewing
directions.
3.6.2.1 Format and use of cr.an
This file contains 32 chunks [C] of 512 bytes each.
Each chunk contains the complete animation information for one character.
x*512 : start character x animation definition [C]
Each chunk has 8 subchunks of 64 bytes. A subchunk [SC] describes the
animation frames to take for a certain action. The actions are
[C]+0000 : [SC] standing
[C]+0040 : [SC] walking
[C]+0080 : [SC] in combat
[C]+00c0 : [SC] attack
[C]+0100 : [SC] attack
[C]+0140 : [SC] attack
[C]+0180 : [SC] attack
[C]+01c0 : [SC] dying
The use of the attack animations differs from critter to critter since not
all critters have 4 different attacks. If a critter has magical and melee
attacks, the melee attacks come first.
Each action is split into 8 animation sequence [AS] definitions for the