File: u7tech.txt

package info (click to toggle)
exult 1.12.0-2
  • links: PTS, VCS
  • area: contrib
  • in suites: forky, sid
  • size: 43,608 kB
  • sloc: cpp: 169,917; xml: 7,400; yacc: 2,850; makefile: 2,419; java: 1,901; ansic: 1,654; lex: 673; sh: 539; objc: 416
file content (1150 lines) | stat: -rw-r--r-- 47,627 bytes parent folder | download | duplicates (3)
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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
**** TECHNICAL REFERENCE AND INTERNAL FORMATS OF ULTIMA7 FILES $Revision: 1.25 $ ****

This is a list of all the U7 files I have studied while developing U7Wizard.
You will find in here technical descriptions of format and content of the
 files. 
Each time you see a "?" in this file, this means I was unable to find the
 meaning of some data.
You can help complete this technical reference by sending your remarks and
 discoverings to u7wizard@pulsar.eu.org

You can download the latest version of this document
from the U7Wizard Official Web Site:
  http://www.pulsar.eu.org/wizard/ultima/u7wizard.htm
    "U7Wizard: The Ultimate World & Scenery Editor for the U7 game engine"

You can freely redistribute this document as long as you don't modify it.
You are not allowed to make profit using the informations contained in this
document.

The author cannot be held responsible for any damage or other consequences of
using this document.
This document is unofficial. It is the result of pure guess.
No reverse-engineering of machine code was involved in this process.
"Ultima 7", "The Black Gate" and "Serpent's Isle" are registered trademarks
 from Origin Systems, Inc.

Olivier Marcoux
-----------------------------------------------------------------------
I decided to leave Olivier's notes at the top. He's done much more than
myself in figuring things out and assembling information. However, I need
a document for my own purposes...so, I'm making notes here as I find out
more and making the odd correction
-----------------------------------------------------------------------
HISTORY

1.0       First public release (Olivier, we owe you one)
...       <- You are here
?.?       An ongoing voyage of discovery. We'll get back to you

-----------------------------------------------------------------------
DATA TYPES

Simple data types used in the description of the formats:
  char    = unsigned 8 bits representing a character
  shortint= signed 8 bits
  byte    = unsigned 8 bits
  uint16 = signed 16 bits
  int16    = unsigned 16 bits
  longint = signed 32 bits

When describing the format of the data, i will use the following conventions:
A = int16 [b0=.. bF=..]
  means that A is a int16 (b0..bF are the description of each byte)
A = nn B
  means that A is composed by nn times B
A = B, C, D
  means that A is composed by B followed by C followed by D
A = set of B
  means that A is composed by a certain number of B
A = B | C
  means that A can be composed by either B or C
xx        (2 hex digits)
  means a byte constant
xxxx      (4 hex digits)
  means a int16 constant
xxxxxxxx  (8 hex digits)
  means a longint constant

Chunk items = shapes coming from the U7CHUNKS map file
Fixed items = shapes coming from U7IFIX files
Game items  = shapes coming from U7IREG files

-----------------------------------------------------------------------
COLLECTION FILE FORMATS

U7 games make extensive use of Flex Files.
A flex file is a collection of objects, it is composed of:
-a header (128 bytes long)
  header  = title, magic1, count, magic2, d1..d9
  title   = $50 characters (optionnal, filled with 00s)
  magic1  = longint (seems to be always $FFFF1A00)
  count   = longint (number of object in table, including empty objects)
  magic2  = longint (seems to be always $000000CC)
  d1..d9 = longints (often set to 0, but sometimes used, meaning?)
-a table of references
  reference = offset, size
  offset    = longint (relative to the beginning of the file)
  size      = longint
  note: empty objects are referenced as null offset and null size
-the objects data (in the same order as declared in the table)
  the format depends on the object type

struct	flex_hdr
	{
	char	title[80];
	uint32	magic1;
	uint32	count;
	uint32	magic2;
	uint32	padding[9];
	};

struct	flex_reference_entry
	{
	uint32	offset;
	uint32	size;
	};

U7 games use also IFF files. (Interchange File Format)
An IFF file is a collection of file associated with their type/name.
It is composed of:
-a header (12 bytes long)
  header  = 'FORM', size, type
  size    = reversed longint (size of the file excluding the first 8 bytes)
  type    = 4 chars representing the type of data contained in the IFF file
-the objects entries
  entry   = type, size, object, [even]
  type    = 4 chars representing the type of this object
  size    = reversed longint (size of the entry excluding the first 8 bytes)
  even    = 1 byte (set to 0) present only to get an even number of bytes
  (the objects found in U7 IFF files have the following format:)
  object  = name, data
  name    = 8 chars (filled with 0s)
  data    = the data of the object

struct	IFFhdr
	{
	char	form_magic[4];
	uint32	size;
	char	data_type[4];
	};
struct	IFFobject
	{
	char	type[4];
	uint32	size;
	char	even;
	};
struct	u7IFFobj
	{
	char	name[8];
	char	data[];	// Variable
	};

U7 games use also table files.
A table file is a collection of object of the same type. It is composed of:
-a table of reference
  reference = info, offset
  info    = 2 bytes (meaning?)
  offset  = longint (relative to the beginning of the file)
-the objects entries (in the same order as declared in the table)
  entry   = size, data
  size    = int16 (including the size int16)
  data    = the data of the object

U7 games use also enumeration files.
An enumeration file is a short collection of data of same type/length
It is composed of:
  enumeration = size, entries
  size    = byte (number of entries)
  entry   = depends of the file, constant length

-----------------------------------------------------------------------
COMMON OBJECTS

Here is a description of the known object type that can be found in
a flex or iff file. Remember that the size of each object is given in the
flex/iff entries so that you can calculate the size of the variant parts
of the object

* Tiles
This is a set of graphic tile representing a certain type of floor that
can appears on the ground in the game view. One tile is 8x8 pixel large
Format:
  tiles = set of tile
  tile  = 8x8 pixel
  pixel = byte (index inside the color palette)

* Shape
This is the graphic representing any item that appears on the game view
except floor tiles. The graphic can include transparent area.
A shape represent a type of object. One shape can have many frames representing
the different appearance of this kind of object. Each frame is describe as a
set of "slices" composing the non-transparent area of the graphic.
A shape can be found in a flex file or as a separate .SHP file
Format:
  shape   = size, set of offset, set of frame
  size    = longint (should be same as in flex table)
  offset  = longint (one for each frame, relative to beginning of shape)
  frame   = rightX, leftX, leftY, rightY, set of slice
    (coordinates are positive distance from the hot spot of the shape)
  slice   = int16=0000   (if end of frame)
          | slength, offsetX, offsetY, scontent
    (a slice represents several pixels on the same line)
  slength = int16 [b0    =type of slice (0=standard, 1=compressed)
                  b1..bF=length in pixel]
  offsetX = uint16 (relative to hot spot)
  offsetY = uint16 (relative to hot spot)
  scontent= set of pixel  (if standard slice)
          | set of block  (if compressed slice)
  block   = blength, bcontent
  blength = byte [b0    =type of block (0=standard, 1=repeated pixel)
                  b1..b7=length in pixel]
  bcontent= set of pixel  (if standard block)
          | pixel         (if repeated pixel block)

* Palette
A palette is an array describing the RGB values for 256 color indexes
This format is compatible with the bios call for setting a palette.
A palette can be found in a flex file or as a separate .PAL file
Format:
  palette = 256 rgb
  rgb     = red green blue
  red     = byte (0..3F)
  green   = byte (0..3F)
  blue    = byte (0..3F)

* Font
A font is simply a shape where each frame represents the graphic for each
ASCII letter
Format:
  font    = shape
Note: the number of frame of a shape is not limited to 32 as
      suggested by the U7CHUNKS file

* String
A string is a short single line of text ending with a null char
Format:
  string    = set of char

* Text
A text is a like a text file, composed with lines of characters.
The texts used in the main menu contains backslashed sequences that
indicates the output format of the lines:
      \Px   include picture number x (frame of MAINSHP.FLX shape 14h)
      \C    center line
      \L    left-aligned line
Format:
  text    = set of char (with 0D 0A at end of lines)

* Midi music
There are 2 kind of midi music found in flex files:
-MID music that share the same format as a .MID file
  these musics can be extracted and saved as a .MID file to be played
  for example with Windows Media Player
-XMI music & special effects that share the same format as a .XMI file
  these musics can be extracted and saved as a .XMI file to be played
Note: I don't know of a player for such XMI files but there must be some
      Origin FX screen saver uses these files
The format of such file is beyond the scope of this document

* Vocal speech
This contains a vocal waveform that share the same format as a .VOC file
These speeches can be extracted and saved as a .VOC file to be heared
  for example with WinAmp
The format of such file is beyond the scope of this document
There's an internet FAQ on this file format. Unusually, the 'number of channels'
field seems to contain bogus data, and there seems to be some crud at the
beginning and end of each VOC. Trimming 32 bytes off each end eliminates
the crackle that it causes,

* Drivers
This is used to store various drivers in a flex file, for example sound
cards drivers.
Format: seems to be pure machine code

-----------------------------------------------------------------------
STATIC DIRECTORY

Here is a description of the files found in the STATIC directory:
(some infos here are specific to Serpent's Isle)

U7MAP:        12x12 regions
  region  = 16x16 chunkID
  chunkID = int16 (0..$C00-1)
U7CHUNKS:     $C00 chunks
  chunk   = 16x16 shapeID
  shapeID = int16 [b0..b9=shapeType  (0..$400-1)
                  bA..bE=shapeFrame (0..$20-1)
                  bF=? ]
SHPDIMS.DAT:  $400-$96 shpdims  (one for each Game Shape)
  shpdims = dimY, dimX
  dimY    = byte [b0: obstacle in N-S direction?
                  b1..b7: Y dimension of the shape=number of tiles covered?]
  dimX    = byte [b0: obstacle in W-E direction?
                  b1..b7: X dimension of the shape=number of tiles covered?]
WGTVOL.DAT:   $400 wgtvol       (one for each Game Shape & Tiles)
  wgtvol  = weight, volume
  weight  = byte: weight of the shape (in 0.1 stone)
  volume  = byte: volume of the shape
    (stone is the unit used in the inventory window in the game)
TFA.DAT:      $400 entries (one for each Game Shape & Tiles)
  tfa     = $400 triplet
  triplet = tfa1, tfa2, tfa3
  tfa1    = byte [b0..1 =?
                  b2    =animated shape
                  b3..4 =?
                  b5..b7=height of shape]
  tfa2    = byte [b0..b6=?
                  b7    =is transparent (cannot be selected, cannot place item on it)]
  tfa3    = byte [b0..b2=X size of the shape - 1  (number of tiles covered)
                  b3..b5=Y size of the shape - 1  (number of tiles covered)
                  b6    =is a light source
                  b7    =contains transparency colors (light,dark,blood)]
SHAPES.VGA:   flex file with $464 shapes
  $0..$95     the Game Tiles (floor)
  $96..$3FF   the Game Shapes
  $400..$40B  extra shapes (sex/skin/dress variants of Avatar)
  $40C..$463  empty
FACES.VGA:    flex file with shapes
  (represents the face of the people you can speak with)
  there are also some full-screen drawings that appears during the game:
   $100       full-screen deamon from The Black Sword
   $125..$127 full-screen serpents
   $128       full-screen guardian
   $12C       full-screen semi-transparent serpent
  and some strange faces :
   $103,$104  ?
   $106       a cat speaking ?
   $129       weird!?
SPRITES.VGA:  flex file with shapes
  (used to display maps or special effects during the game)
PAPERDOL.VGA: flex file with shapes
  (parts of suits,weapons,armor,etc.. that are combined on the inventory
  screen to show what the character is wearing)
GUMPS.VGA:    flex file with shapes
  (parts of the user interface of the game like bags, windows, buttons...)
FONTS.VGA:    flex file with fonts
TEXT.FLX:     flex file with lots of string (name of shape, quotes, cheat texts)
PALETTES.FLX: flex file with palettes
MAINSHP.FLX:  flex file with various objects used in main menu
Content for Black Gate/Forge of Virtue - palette from INTROPAL.DAT
  $0        shape (male face)
  $1        shape (female face)
  $2        shape (main screen)			0
  $3        font
  $4        shape ("view introduction")		0
  $5        shape ("start new game")		0
  $6        shape ("view credits")		0
  $7        shape ("return to menu")		0
  $8        shape ("journey onward")		0
  $9        font
  $A        shape ("sex:")
  $B        shape ("male/female")
  $C        shape ("name")
  $D        text (Guardian speech...)
  $E        text (Credits)
  $F        data (Guardian Face animation events)
  $10       text (Quotes)
  $11       shape ("view quotes")
  $12       shape ("view endgame")
  $13       ???
  $14       shapes ("rated mp-13/origin fx/dana glover/voodoo")
  $15       text (lose message)
  $16       shape ("male")
  $17       shape ("female")
  $18       ???
  $19-$1D   empty

The Guardian Face animation events have the following format:
  Array of face animation entries
  entry = time, code
  time      = int16 time, in milliseconds, from beginning of voice playback
  code      = byte
          $00         End of data
          $01         Set eyebrows to "angry", keep eyes unchanged (frames 1/2/3)
          $02         Set eyebrows to "neutral", keep eyes unchanged (frames 4/5/6)
          $03         Set eyebrows to "raised", keep eyes unchanged (frames 7/8/9)
          $04         Fully open eyes, keep eyebrows unchanged (frames 1/4/7)
          $05         Partially open eyes, keep eyebrows unchanged (frames 2/5/8)
          $06         Fully closed eyes, keep eyebrows unchanged (frames 3/6/9)
                      Eye frame descriptions:
                       1  "Angry" eyebrows, eyes fully opened, looking ahead
                       2  "Angry" eyebrows, eyes half-opened, looking ahead
                       3  "Angry" eyebrows, eyes closed, looking ahead
                       4  "Neutral" eyebrows, eyes fully opened, looking ahead
                       5  "Neutral" eyebrows, eyes half-opened, looking ahead
                       6  "Neutral" eyebrows, eyes closed, looking ahead
                       7  "Raised" eyebrows, eyes fully opened, looking ahead
                       8  "Raised" eyebrows, eyes half-opened, looking ahead
                       9  "Raised" eyebrows, eyes closed, looking ahead
                      10  "Raised" eyebrows, eyes fully opened, looking down
          $07         Sets eyes to frame 10, but does not change last eye frame
                      for the purposes of codes $01 to $06
          $08 to $16  Set mouth frame to code-8. Frame 0 is background, and it
                      should not be used here.
          Above $17   Invalid/do not use

Content for Serpent Isle/Silver Seed
  $0        shape (the "warp" screen)
  $1        palette (to be used with the previous screen)
  $2        shape ("serpent's isle", the main menu title)
  $3        shape (mask for the portrait?)
  $4..$8    shape (menu options)
  $9        font  (used when the user types the name of the Avatar)
  $A..$C    shape (avatar options)
  $D        empty
  $E        text  (credits)
  $F        empty
  $10       text  (quotes)
  $11,$12   shape (additionnal main menu options)
  $13       shape (mouse cursor)
  $14       shape (pictures used in texts)
  $15       text  (game lost text)
  $16..$19  shape (additionnal avatar options)
  $1A       palette (to be used with previous shapes)
  $1B..$20  mid music
  $1B..$27  empty

ENDSHAPE.FLX: flex file with various objects used in intro (Black Gate only)
  The palettes from the FLEX file INTROPAL.DAT should be used - the palette
  index is specified in brackets

  $0        Thorns on left
  $1        Thorns on right
  $2        Top left moongate
  $3        Right moongate
  $4        Bottom left moongate
  $5        Bottom right moongate
  $6        Cloth map (2)
  $7        Top right computer
  $8        Bottom right computer
  $9        Top left computer
  $A        Bottom left computer
  $B        Orb
  $C        Fist
  $D        Ultima VII
  $E        Butterfly
  $F        "Ultima VII The Black Gate The Quest Begins Christmas 1991"
  $10       "The Quest Begins Christmas 1991"
  $11       "Lord British presents..." (3)
  $12       Trees
  $15       "Something is obviously amiss"
  $16       "It has been a long time since your last visit to Britannia"
  $17       "The mystical Orb beckons you..."
  $18       "It has opened gateways to Britannia in the past"
  $19       "Behind your house lies the circle of stones"
  $1A       "Why is a Moongate already there?"
  $1B       Empty
  $1C       "You have but one path to the answer"
  $1D       Small intro screen 
  $1E       Guardian's mouth
  $1F       Guardian's forehead
  $20       Guardian's eyes
  $21       Guardian "emerging 1" (frames 0-9)
  $22       Guardian "emerging 2" (frames 0-9)
  $23       Guardian "emerging 3 (final)" (frames 0-15)
  
ENDGAME.DAT
  $0        FLIC with guardian coming into Black Gate
  $1        FLIC with Black Gate exploding
  $2        FLIC with flickering torches
  $3        Font
  $4        Font
  $5        Font
  $6        Font
  $7        Voice file
  $8        Voice file
  $9        Voice file
  $A        Shape file

INITGAME.DAT: flex file with archived files
  (these files are to be extracted to the GAMEDAT directory with their
   original name. they represent the state of a new game. the format is the
   same for the saved games GAMExx.U7)
  archived file = filename, data
  filename      = 13 characters giving the filename (filled with 00s)
  data          = the remaining is the file content
SISPEECH.SPC: flex file with vocal speech
ADLIBMUS.DAT: flex file with midi music (for Adlib sound card)
MT32MUS.DAT:  flex file with midi music (for Roland MT32 sound card)
ADLIBSFX.DAT: flex file with xmi?midi? special effects (for Adlib sound card) ?? Instrument voices? What?
MT32SFX.DAT:  flex file with xmi?midi? special effects (for Roland MT32 sound card) ?? More questions, as above
MAINMENU.TIM: flex file with instrument timbres (for the main menu)
  (This is used by the main menu. Format unknown?) [ NOT IN TBG ]
MAINMENU.DRV: flex file with drivers (for the main menu) [ NOT IN TBG ]
SNDDRVRS.DAT: flex file with drivers (for each type of supported sound cards)
XFORM.TBL:    flex file with shape transform tables
  These are matrix used to transform the color of pixels that are seen
  through semi-transparent effect (glass, cloud, blood...)
  table     = 256 new_color (one for each possible color index)
  new_color = byte  (the new color index to use)

  There are 11 of these tables, and they're assigned to the
  17 translucent colors (0xee-0xfe) going backwards; i.e., table 0
  applies to color 0xfe, 1 to color 0xfd, 2 to 0xfc,... 16 to 0xee.
  When the renderer paints one of the translucent colors, it takes the
  pixel that's already in the frame buffer and looks it up in the
  appropriate xform table to get its replacement.

POINTERS.SHP: shape file
  (contains the mouse cursors used in the game)
ENDSCORE.DAT: A RIFF file containing what _appears_ to be some kind of midi 
  data, but not in the usual midi format. Could it be the XMI format that much
  of the rest of this file refers to? In most instances so far, this document 
  incorrectly describes regular midi files as XMI files.
INTRO.DAT / ENDGAME.DAT: iff file with intro/endgame animation data
  (contains FLIC animations, font, shape, speeches)
INTROADM.DAT: MIDI file containing 6 midi tracks for the introductory sequence.
    I suspect this to be a flex file, and further suspect it to be for the
    adlib sound card.
INTRORDM.DAT: The same, but I'm guessing that this is for the roland MT32.
INTROSND.DAT: VOC file. The Guardian's chilling initial announcement.
ADLIB.ADV:    driver for the Adlib sound card
MT32MPU.ADV:  driver for the Adlib sound card
SBDIG.ADV:    driver for the SoundBlaster sound card
SBPDIG.ADV:   driver for the SoundBlaster Pro sound card
XMIDI.AD:     table file with data relative to midi music
XMIDI.MT:     table file with data relative to midi instruments
WIHH.DAT:     wihh entries for the game shapes
  table   = $400 offset
  offset  = int16  (0 if no object associated with the shape)
  (the offsets are relative to the beginning of the file and point to objects:)
  object  = 32 int16's (meaning? one per shape frame?)
WEAPONS.DAT:  weapons enumeration (jsf, Marzo)
  weapon    = type, family, ammo, damage, flags0, range, flags1, flags2, powers,
              1 byte (0), usecode, strikeSFX, hitSFX, 2 bytes (0)
  type      = int16 (shape type)
  family    = int16 (if positive, consume ammo of this family if in in quiver;
                     if -3, consume item quantity when ranged;
                     if -2, consume item quality;
                     if -1, weapon is the ammo)
  ammo      = int16 (if positive, shape to be used for missile when fired;
                     if -3, use weapon shape for projectile;
                     if -1, projectile is invisible)
  damage    = 1 byte, positive.
  flags0    = 1 byte, bit flags:
          b0 == lucky (easier to hit with)
          b1 == explodes
          b2 == no blocking?
          b3 == delete depleted weapon if family == -2
          [b4..b7]: damage type
                    0 == normal damage, causes bleeding
                    1 == fire damage
                    2 == magic damage
                    3 == lightning damage, ignores armor
                    4 == ethereal damage, ignores armor
                    5 == sonic/poison damage, ignores armor
                    6, 7 == unnamed/unused damage types, they nevertheless work
                            (even immunity and vulnerability flags)
  range     = 1 byte
          b0 == always hits
          [b1..b2]: uses
                    0 == hand-to-hand weapon
                    1 == poor thrown (seems to be +6-dist to hit)
                    2 == thrown (seems to be +6-dist/2 to hit)
                    3 == ranged (seems to be +6-dist/4 to hit; unsure about it)
          [b3..b7]: Strike range for uses < 3; max range for uses == 3;
		            for 0 < uses < 3, if farther away than this, throw weapon
  flags1    = 1 byte
          b0 == returns
          b1 == must target object, unless if through an usecode attack
                (e.g., firedoom staff can attack empty tile, bow can't)
          [b2..b3]: Very fast missile if nonzero, check missile speed otherwise
          [b4..b7]: Missile rotation: # of frames added each step
  flags2    = 1 byte
          [b0..b1]: Actor frames to use on melee
          [b2..b3]: Actor frames to use on ranged
          b4 == unknown
          [b5..b7]: missile speed
                    0 == fast
                    1, 2 == medium (seems to be no difference between 1 and 2)
                    3+ == slow (they all seem equally slow)
  powers    = 1 byte, bit flags (special powers), meaning:
          b0 == sleep
          b1 == charm
          b2 == curse
          b3 == poison
          b4 == paralyze
          b5 == magebane
          b6 == ?? (insects have this).
          b7 == harmless (SI)
  usecode   = int16 (Usecode function.  Called upon strike with event=4.)
  strikeSFX = int16.  1 + SFX# to play during attack.
  hitSFX?   = int16.  Doesn't seem to be used in the originals.

AMMO.DAT:     ammunitions enumeration
  ammunition= type, family, type2, damage, flags0, 1 byte (0), damtype, powers,
              2 bytes (0)
  type      = int16 (shape type)
  family    = int16 (shape type of the base ammunition eg: lucky arrow->arrow)
  type2     = int16 (if -1, do not show sprite [does not override weapon setting];
                     if -3, use ammo type as projectile;
					 otherwise, shape to use as projectile)
  damage    = byte (extra damage)
  flags0    = byte
          b0 == lucky (easier to hit with; accumulates with weapon setting)
          b1 == always hits (OR'ed with weapon setting)
          b2 == returns (OR'ed with weapon setting)
          b3 == no blocking?
          [b4..b5]: drop type
                    0 to drop on misses
                    1 to drop always
                    2 to drop always
                    3 means homing (e.g., death vortex) IF also explodes
          b6 == Explodes/bursts (OR'ed with weapon's)
          b7 == ???
  damtype   = 1 byte
          [b0..b3]: ???
		  [b4-b7]: damage type, like a weapon's; used instead of weapon's
		           damage type unless == 0
  powers    = 1 byte, exactly like weapon's. A harmless missile may call usecode
              0x7e1 on hit in SI.
ARMOR.DAT:    armors enumeration
  armor     = type, defense, 1 byte (0), immunity, 5 bytes (0)
  type      = int16 (shape type)
  defense   = byte (points of damage removed from a successful attack;
              seems to be randomized, and ignored by some damage types)
  immunity  = 1 byte, bit flags (bit i means immune to damage type i)
MONSTERS.DAT: monsters enumeration
  monster   = type, str, dex, int, com, ar, 1 byte(?), wp, flags, vulnerab,
              immunity, flags2, attack+?, equip, 2 bytes(0), sfx, 7 bytes(0)
  type      = int16 (shape type)
  str       = byte
          b0 == immune to sleep
		  b1 == immune to charm
		  [b2..b7]: strength
  dex       = byte
          b0 == immune to curse
		  b1 == immune to paralysis
		  [b2..b7]: dexterity
  int       = byte
          b0 == immune to poison
		  b1 == ???
		  [b2..b7]: intelligence
  com       = byte
          [b0..b1] == alignment
		  [b2..b7]: combat skill
  ar        = byte
          b0 == may split when killed (unless killed by vulnerability)
		  b1 == can't die
		  b2 == immune to sleep/charm/curse/paralysis
		  b3 == Protected from death spells?
		  [b4..b7]: armor
  wp        = byte
          [b0..b3]: reach
          [b4..b7]: damage (only if not using weapon???)
  flags     = 1 byte, bit flags
          b0 == flies
          b1 == swims
          b2 == walks
          b3 == ethereal
          b4 == no body
          b5 == ???
          b6 == start invisible
          b7 == see invisible
  vulnerab  = 1 byte, bit flags (bit i means double damage of damage type i)
  immunity  = 1 byte, bit flags (bit i means immune to damage type i)
  flags2    = 1 byte, bit flags
          b5 == can't yell
          b6 == doesn't bleed
  attack    = byte, partially unknown
          [b0..b2]: Sets initial attack mode based on chance.
          [b3..b7]: ???
  equip     = byte, record number in EQUIP.DAT
  sfx       = byte, sfx to play when striking
EQUIP.DAT:  equipment enumeration
  equipment = 60 bytes (meaning?)
READY.DAT:  weapon ready enumeration
  ready     = type, ready, 6 bytes (0)
  type      = int16 (shape type)
  ready     = byte
          b0 == is spell
          [b1..b2]: zero
          [b3..b7]: weapon slot
SCHEDULE.DAT: schedule file
  schedules = count, activities, sched_types
  count     = longint (number of activities = number of npc with schedule)
  activity  = int16 (index of the type of schedule)
  sched_type= int16 (meaning?)
USECODE     = usecode functions list
  function  = number, size, dseg, cseg
  number    = int16 (number of the usecode function, sometimes linked to shape type)
  size      = int16 (size of the data & code segments)
  dseg      = dsize, data (data segment)
  dsize     = int16 (size of the data)
  data      = texts/data used by the codes (strings are zero-terminated)
  cseg      = args, locals, links, usecodes
  args      = int16 (number of arguments)
  locals    = int16 (number of local variables)
  links     = count, link, ..., link
  count     = int16 (number of link)
  link      = int16 (number of a usecode function that will be called by this function)
  usecodes  = <you will need a usecode disassembler>
LINKDEP1 = usecode functions link dependencies
  (one dependency for each usecode function number plus one, even if the function is not defined in USECODE)
  dependency= index, size
  index     = int16 (index of first pointer for this function in LINKDEP2, starting from 0)
  size      = int16 (size in bytes taken by all functions linked to this function, FFFF if no function)
LINKDEP2 = linked functions pointer list
  list      = pointer, ..., pointer
  pointer   = longint (offset of usecode function inside the USECODE file)
OCCLUDE.DAT = bit array (128 byte = $400 bit)
  one bit per game shape. set if the shape completely occludes the space
  it is covering (not sure?)
U7VOICE.FLX = flex file with what we believe to be midi instrument voices.
	The format for each voice is uncertain
U7IFIXnn    = flex file with fixed items list
  (nn represents the region number.
   There are 16x16 lists in each file, one for each chunk in the region.
   The lists contain the static items found in the given chunk.
   Static items are items which can't interact with the user)
  list    = entries (each entry is 4 bytes long)
  entry   = coord, lift, shapeID
  coord   = byte [b0..b3=Y coord inside chunk
                  b4..b7=X coord inside chunk]
  lift    = byte [b0..b3=lift level
                  b4..b7=0]
  shapeID = int16 [b0..b9=shapeType  (0..$400-1)
                  bA..bE=shapeFrame (0..$20-1)
                  bF=0]


-----------------------------------------------------------------------
GAMEDAT DIRECTORY

Here is a description of the files found in the GAMEDAT directory:

MAPCOORDS.DAT = coordinates of the avatar
  coords  = X, Y, d1, d2, d3, d4
  X       = int16 (X coordinate 0..3071)
  Y       = int16 (Y coordinate 0..3071)
  d1,d2,d3= byte (meaning?)
  d4      = int16 (meaning?)

IDENTITY  = text file containing the name of the world
  one single line, followed by RC LF (0D 0A)
  can also be followed by EOF (1A)
  it "ULTIMA7", "FORGE", "SERPENT ISLE", "SILVER SEED"

RANDSEED  = current value of the seed used by the random number generator
  seed    = longint

U7IREGnn    = same meaning as U7IFIX but for game items (different format)
  Each U7IREGnn file contains the game items for the region number nn.
  Game items are items the user can interact with: move, use etc...
  Note: fixed items items from 2 chunks around the Avatar position are copied in
    the U7IREG files
  reg_items = 16x16 chk_items (one for each chunk of the region)
  chk_items = item, item, ..., item, 00 (or just 00 if no item for this chunk)
  item      = standard | extended | extra
  standard  = 06, XY, shapeID, lift, quality
  extended  = 0C, XY, shapeID, type, proba, data1, lift, data2, [content]
  extra     = 12, XY, shapeID, extradata
    (content is present if shapeID represents a container and type not null)
  content   = item, item, ..., item, 01
  shapeID   = int16 [b0..b9=shapeType  (0..$400-1)
                    bA..bE=shapeFrame (0..$20-1)
                    bF=0]
  lift      = byte [b0..b3=? (inside:6, outside:0..3 - same for all items
                              in region, 4 seems to be unused NPC)
                    b4..b7=lift level]
  quality   = byte (quality of the item)

  for outside items:
  XY        = X, Y
  X         = byte (X coordinate inside the region)
  Y         = byte (Y coordinate inside the region)

  for inside items: (item in content)
  XY        = referent of the parent container
  referent  = int16 (offset of the data inside U7IBUF.DAT)

  virtue stones have length 0xc, with:
  entry[4] = tilex  (cx,tx)
  entry[5] = tiley  (cy,ty)
  entry[6] = superchunk #.

  for containers:
  type      = referent of the first item in the container (0000 if empty)
  proba     = byte (? always 00 or current region number)
  data1     = quality, quantity
  data2     = resist, flags
  quality   = byte (00: no key 01..F9: matching key FA..FF: trap
                    for corpse, 00..01: npc# >> 7 02: can't be raised)
              Exult: for corpse, 00: dead NPC 01..FF: unused
  quantity  = byte (00 or 01 or npc# & $7F if corpse can become NPC)
  resist    = byte (attack/lockpicking resistance points)
  flags     = byte [b0:invisible
                    b1..b2:0
                    b3:okay to take
                    b4:?
                    b5:halt flag?
                    b6:0
                    b7:set if human NPC is carrying lit light sources]
  note: key-locked containers cannot be lockpicked but can be attacked if
  resistance points are > 0

  for actors:
  type      = referent of the first item in the container (0000 if empty)
  proba     = byte (? always 00 or current region number)
  data1     = attack, quantity
  data2     = hps, flags
  attack    = byte (the NPC's attack mode)
  quantity  = byte (?)
  hps       = byte (actor's current health)
  flags     = byte [b0:invisible
                    b1..b2:0
                    b3:okay to take
                    b4:?
                    b5:halt flag?
                    b6:0
                    b7:set if human NPC is carrying lit light sources]

  for barges:
  type      = sizeX, sizeY
  proba     = byte (? id of the barge?)
  data1     = flags, 00
  data2     = 0000
  sizeX     = byte (X number of tiles covered by the barge)
  sizeY     = byte (Y number of tiles covered by the barge)
  flags     = byte [b0:0
                    b1:currently horizontal
                    b2:? same as b1 except for the flying carpet
                    b3..b7:0]

  for a spellbook:
  extradata = circle1, .., circle5, lift, circle6, .. circle9, flags
  circle    = byte [b0=book contains spell 1 of this circle
                    ...
                    b7=book contains spell 8 of this circle]
  flags     = longint  [b0..b17=?
                        b18..b1f=bookmarked spell]

  for all egg items: (if shapeID represents an Egg)
  type      = int16 [b0..b3=egg type
                    b4..b6=criteria
                    b7=nocturnal
                    b8=once ever
                    b9=hatched
                    bA..bE=distance for activation
                    bF=auto-reset]
  proba     = byte (probability for activation 0..100)

  for none egg (0):

  for monster egg (1):
  data1     = mode, workType
  mode      = byte [b0..b1:alignment
                    b2..b7:number]
  workType  = byte
  data2     = int16 (type of creature, 6 bits frame, 10 bits shape)
  data3     = int16 (Exult:  data3>0 => data3 is shape, data2(7:0) is frame)

  for jukebox egg (2):
  data1     = score, flags
  score     = byte
  flags     = byte [b0:continuous
                    b1..b7=0]
  data2     = 0000

  for sound effects egg (3): (must be verified?)
  data1     = sfxNum, flags
  sfxNum    = byte
  flags     = byte [b0:continuous
                    b1..b7=0]
  data2     = 0000

  for voice egg (4):
  data1     = speechNum, 00
  speechNum = byte
  data2     = 0000

  for usecode egg (5):
  data1     = quality, quantity
  quality   = byte
  quantity  = byte
  data2     = int16 (usecode function number)

  for missile egg (6): (must be verified?)
  data1     = int16 (missile type)
  data2     = direction, frequency
  direction = byte
  frequency = byte

  for teleport egg (7):
  data1     = quality, schunk
  quality   = byte
  schunk    = byte
  data2     = x, y (coordinates inside region)
  x         = byte
  y         = byte
  Note: if quality = 255, jumps to the given coordinates
        otherwise, jumps to the path egg (9) with the same quality

  for weather egg (8):
  data1     = weather, duration
  weather   = byte (type of weather)
  duration  = byte (number of minutes, null=continuous)
  data2     = 0000

  for path egg (9):
  data1     = quality, nextQual
  quality   = byte
  nextQual  = byte (next quality)
  data2     = 0000

  for button egg (10): (must be verified?)
  data1     = area, 00
  area      = byte  (area of effect)
  data2     = 0000

  for intermap egg (11) (Exult only):
  data1     = map, schunk
  map       = byte
  schunk    = byte
  data2     = x, y (coordinates inside region)
  x         = byte
  y         = byte

ITEMNODE.DAT:
  itemnode = first_free, free_count, 0000?, chunks1, ..., chunks4,
             region1, .., region4, region1?
  first_free = referent (of first free block inside U7IBUF.DAT)
  free_count = int16 (number of free blocks)
  chunksN  = 16x16 referent (of first visible shape in each chunk)
  regionN  = byte (region number corresponding to chunksN)

U7IBUF.DAT: Cache file for objects in use (inventories, visible map shapes,...)
  It is composed with 8-bytes blocks that can be referenced by their offset (int16).
  Here is cached all NPC shape & content, all game items from cached regions
   (see ITEMNODE.DAT), all fixed items & chunk items from 2 chunks around
   the Avatar position
  block = next, XY, shapeID, info
  next    = referent (of next item, 0000 when no more item)
  offset = int16
  XY = X, Y     (for outside items)
     | referent (of parent container)
  shapeID = int16
  info = lift, quality  (for standard items)
       | referent (of additionnal infos for extended items)

  additionnal infos:
  block = type, proba, data1, lift, data2  (same as extended item in U7IREG)

PARTY:
  party = companion1, .. companion8, count, ???
  companionN = referent (of Nth companion of the party in U7IBUF.DAT)
  count      = byte (number of companion in party)
  must contain str/int etc.. for the persons

U7NBUF.DAT: Cache file for NPCs in use
  It is composed with 105-bytes NPC definition block
  It contains the whole NPC list. It is build from NPC.DAT when creating a new
  game. The NPCs shape & inventory are in U7IBUF under the given referent.
  npcBlock  = index, referent, status, str, dexterity, intel, combat, activity,
              DAM, 3-bytes?, status2, index2, 2-bytes?, exper, training, primary,
              secondary, oppressor, I-Vr, S-Vr, status3, byte?, target, weapon,
              acty?, SN, V1, V2, 29-bytes?, food, 7-bytes?, name
  index     = int16 (meaning? 1-based?)
  status    = int16 [b0: ?
                    b1..b2: Heading direction (N,E,S,W)
                    b3..b4: Follow/Alignment (Neutral,Good,Evil,Chaotic)
                    b5,b6: True alignment (stored when NPC is charmed)
                    b7: Asleep
                    b8: Charmed
                    b9: Cursed
                    bA: ? (Busy?)
                    bB: In Party
                    bC: Paralyzed
                    bD: Poisonned
                    bE: Protected
                    bF: Dead]
  str       = byte [b0..b4: Strength
                    b5..b6: Skin color
                    b7: Freeze]
  dexterity = byte
  intel     = byte [b0..b4: intelligence
                    b5: Read
                    b6: Tournament
                    b7: Polymorph]
  combat    = byte [b0..b4: Combat skill
                    b5..b6: ?
                    b7: Petra]
  activity  = byte (should be 0..31)
  DAM       = byte (default attack mode 0..9)
  status2   = int16 [b0..b4: Maximum Magic Points (for NPC#0)
                    b0..b4: ID#
                    b5..b7: Temperature (high 3 bits)
                    b8..bC: Mana, Current Magic Points (for NPC#0)
                    b8: Met
                    b9: No Spell Casting
                    bA: Zombie
                    bB..bC: ?
                    bD..bF: Temperature (low 3 bits)]
  index2    = byte (meaning? 0-based? face from FACES.VGA ?)
  exper     = longint (experience points)
  training  = byte (training points)
  primary   = uint16 (primary target NPC#)
  secondary = uint16 (secondary target NPC#)
  oppressor = uint16 (oppressor NPC#)
  I-Vr      = vector (called "I-Vr" in cheat menu, means?)
  S-Vr      = vector (location where the NPC is supposed to be for his schedule)
  vector    = uint16, uint16
  status3   = int16 [b0..b2: D/R (called "D/R" in cheat menu, means?)
                    b3: ?
                    b4: Fly
                    b5: Walk
                    b6: Swim
                    b7: Ethereal
                    b8: Want Primary
                    b9: Sex (M/F)
                    bA: Bleeding
                    bB: In Party
                    bC: Might
                    bD: In Action
                    bE: Conjured
                    bF: Summonned]
  target    = XY
  XY = X, Y
     | referent (of target object)
  X         = byte (X coordinate delta to target tile)
  Y         = byte (Y coordinate delta to target tile)
  weapon    = int16 [b0..b3: 1-based index of weapon in weapons.dat
                    b4: ?
                    b5: Set if targetting tile
                    b6..b7: ?]
  food      = byte (food level)
  SN        = byte (meaning?)
  V1        = int16 (meaning?)
  V2        = int16 (meaning?)
  name      = 16-chars (zero-terminated string)

NPC.DAT: Initial NPC definition (taken from INITGAME.DAT)
  npcDef    = npc1count, npc2count, npc, npc, ..., npc
  npc1count = number of NPC type 1 in this file
  npc2count = number of NPC type 2 in this file
    (there are npc1count+npc2count npc in the file)
  npc       = extended, npcBlock, [inventory]
    (inventory is present if type of extended item not null)
  extended  = part after the 0C of an extended item (see U7IREG)
  header    = 12-bytes?
  npcBlock  = see U7NBUF.DAT file
  inventory = item, item, ..., item, 00
  item      = see U7IREG files

FRAMES.FLG: $400 frame_flag
  frame_flag = longint  (-1 if not applicable)
  (meaning?)

-----------------------------------------------------------------------
USECODE OPCODES

List of arguments that can be found after the opcode byte:
argument size description
<local>    2  zero-based index of a local variable (the first local variables are the arguments of the function)
<jump>     2  offset inside the code segment, relative to beginning of the next opcode
<data>     2  offset of a string inside the data segment
<byte>     1  immediate 8-bits value
<int16>     2  immediate 16-bits value
<link>     2  zero-based index of a usecode function inside the links array
<function> 2  number of a usecode function
<native>   2  index of an external function native to the game engine
<flag>     2  index of a game flag

name  codes description
?           00
?           01
LOOP        02 <local1> <local2> <local3> <local4> <jump>: beginning of a loop
     <local3> gets each value of the <local4> array
     to be verified: <local1> receive the 1-based index of the loop
     to be verified: <local2> receive the number of values in the array
     once the loop is over, <jump> to the end of the loop
?           03
JTRUE/JNZ   04 <jump>: pop a boolean/integer, <jump> if it's true/non-zero  (need to be verified)
JFALSE/JZ   05 <jump>: pop a boolean/integer, <jump> if it's false/zero
JMP         06 <jump>: do an immediate <jump>
CMPS        07 <int16> <jump>: ? (need to be verified)
?           08
ADD         09: pop 2 integers, add them and push the result
SUB         0A: pop 2 integers, substract 1st from 2nd and push the result
DIV         0B: pop 2 integers, divide 2nd by 1st and push the result
MUL         0C: pop 2 integers, multiply them and push the result
MOD         0D: pop 2 integers, operate 2nd modulo 1st and push the result
AND         0E: pop 2 booleans, operate a "and" and push the result
OR          0F: pop 2 booleans, operate a "or" and push the result
NOT         10: pop a boolean, operate a "not" and push the result
?           11
POP LOCAL[] 12 <local>: pop a value inside the given <local>
PUSH TRUE   13: push the boolean TRUE
PUSH FALSE  14: push the boolean FALSE
?           15
TEST >      16: pop 2 integers, test if 2nd is greater than 1st, push the boolean result
TEST <      17: pop 2 integers, test if 2nd is less than 1st, push the boolean result
TEST >=     18: pop 2 integers, test if 2nd is greater or equal to 1st, push the boolean result
TEST <=     19: pop 2 integers, test if 2nd is less or equal to 1st, push the boolean result
TEST !=     1A: pop 2 integers, test if they are different, push the boolean result
?           1B
CONCAT      1C <data>: concatenate the given string to the string register
PUSH        1D <data>: push the given string
ARRAY       1E <int16>: pop the given number of value, create an array with them and push the result
PUSH        1F <int16>: push the immediate 16-bits value
?           20
PUSH LOCAL[]21 <local>: push the value of the given <local>
TEST ==     22: pop 2 integers, test if they are equal, push the boolean result
?           23
CALL        24 <link>: call the given usecode function from the links array
RET         25: return from function
GET         26 <local>: pop an integer index and push the indexed value from the <local> array
?           27
?           28
?           29
?           2A
?           2B
ABORT2      2C: abort the function (need to be verified)
POP RESULT  2D: pop a value and set it as the return value of the function
SLOOP       2E: initiate a loop (always followed by the opcode 02)
CONCAT      2F <local>: concatenate the string from the <local> to the string register
TEST IN     30: pop an array and a value, test if value is inside the array, push the boolean result
?           31 <4 bytes>: ?
RET RESULT  32: push the return value of the function and return from function
SAY         33: say the string register as part of current talk and empty the string register
?           34
?           35
?           36
?           37
CALLIS      38 <native> <byte>: call the external function with the given number of argument on the stack. push the result on the stack
CALLI       39 <native> <byte>: call the external function with the given number of argument on the stack. no result on the stack
?           3A
?           3B
?           3C
?           3D
PUSH REF    3E: push an identifier of the game item for which the usecode function has been called
EXIT        3F: abort the function and any previous call (need to be verified)
?           40: ?
?           41
PUSH FLAG[] 42 <flag>: push the given game flag as a boolean
POP FLAG[]  43 <flag>: pop a boolean as the given game flag
PUSH        44 <byte>: push the immediate 8-bits value
?           45 <byte>: ?
PUT         46 <local>: pop an integer index and a value, replace the indexed value in the <local> array
CALL        47 <function>: call the given usecode function (must appear also in the links array)
PUSH EVENT  48: push an integer that identify the reason why the usecode function has been called
?           49
ARRAYADD    4A: pop a value and an array, add the value at the end of the array and push the result
POP EVENT   4B: pop an integer and set it as the current reason identification
?           4C through FF
-----------------------------------------------------------------------
WHAT REMAINS TO BE EXPLAINED


how does the association "NPC" <-> "FACES.VGA" work
some shapes have different title for each frame (eg: desk items)
what does bit 15 of shapeID mean
some infos about NPCs are not yet found

plus, everywhere you find a "?" in this file, there is something i was unable to figure out.

-----------------------------------------------------------------------

Olivier Marcoux
u7wizard@pulsar.eu.org