home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / games / utils / ztools.lha / ztools / src / infodump.c next >
C/C++ Source or Header  |  1992-12-17  |  27KB  |  886 lines

  1. /* infodump.c V1.2
  2.  *
  3.  * Infocom dictionary dumper, etc. for type 3, 4, 5 and 6 games. If you have
  4.  * Zork I then by defining ZORKI you will get a detailed list of object
  5.  * properties. Properties numbers and use vary between games so this only works
  6.  * for ZORK I.
  7.  *
  8.  * Requires txio.c and tx.h
  9.  *
  10.  * Usage: infodump story-file-name
  11.  *
  12.  * Mark Howell 28 August 1992 howell_ma@movies.enet.dec.com
  13.  *
  14.  * History:
  15.  *    Fix verb table display for later type 4 and 5 games
  16.  *    Fix property list
  17.  */
  18.  
  19. #include "tx.h"
  20.  
  21. typedef struct wentry {
  22.     struct wentry *flink;
  23.     unsigned short text;
  24.     int number;
  25. } wentry_t;
  26.  
  27. #ifdef __STDC__
  28. static void show_header (void);
  29. static void show_synonym (void);
  30. static void show_object (void);
  31. static void print_property_list (unsigned long *, int);
  32. #ifdef ZORKI
  33. static int print_property_values (int, int, int, unsigned long *);
  34. static void print_string (unsigned long *);
  35. #endif
  36. static void show_tree (void);
  37. static void print_object (int, int);
  38. static void print_object_desc (int);
  39. #ifndef ONE_COLUMN
  40. static void show_dictionary (void);
  41. #else
  42. static void show_dictionary2 (void);
  43. #endif
  44. static zword_t get_object_address (zword_t);
  45. static void show_verb_table (void);
  46. static void load_words (int);
  47. static wentry_t *lookup_word (wentry_t *, int);
  48. static void free_words (void);
  49. static void fix_dictionary (void);
  50. #else
  51. static void show_header ();
  52. static void show_synonym ();
  53. static void show_object ();
  54. static void print_property_list ();
  55. #ifdef ZORKI
  56. static int print_property_values ();
  57. static void print_string ();
  58. #endif
  59. static void show_tree ();
  60. static void print_object ();
  61. static void print_object_desc ();
  62. #ifndef ONE_COLUMN
  63. static void show_dictionary ();
  64. #else
  65. static void show_dictionary2 ();
  66. #endif
  67. static zword_t get_object_address ();
  68. static void show_verb_table ();
  69. static void load_words ();
  70. static wentry_t *lookup_word ();
  71. static void free_words ();
  72. static void fix_dictionary ();
  73. #endif
  74.  
  75. static char alternate_alphabet[3][26];
  76. static wentry_t *wentry_head = NULL;
  77.  
  78. #ifdef __STDC__
  79. int main (int argc, char *argv [])
  80. #else
  81. int main (argc, argv)
  82. int argc;
  83. char *argv[];
  84. #endif
  85. {
  86.     if (argc != 2) {
  87.         fprintf (stderr, "Usage: %s story-file\n", argv [0]);
  88.         exit (EXIT_FAILURE);
  89.     }
  90.  
  91.     open_story (argv [1]);
  92.  
  93.     configure (V3, V6);
  94.  
  95.     load_cache ();
  96.  
  97.     if (h_type == V6 && h_alternate_alphabet_offset) {
  98.         unsigned long offset;
  99.         int i, j;
  100.  
  101.         offset = (unsigned long) h_alternate_alphabet_offset;
  102.         for (i = 0; i < 3; i++) {
  103.             for (j = 0; j < 26; j++)
  104.                 alternate_alphabet[i][j] = read_data_byte (&offset);
  105.             lookup_table[i] = &alternate_alphabet[i][0];
  106.         }
  107.     }
  108.  
  109.     fix_dictionary ();
  110.  
  111.     show_header ();
  112.  
  113.     show_synonym ();
  114.  
  115.     show_object ();
  116.  
  117.     show_tree ();
  118.  
  119.     if (h_type != V6) /* Doesn't work for type 6 games yet */
  120.         show_verb_table ();
  121. #ifndef ONE_COLUMN
  122.     show_dictionary ();
  123. #else
  124.     show_dictionary2 ();
  125. #endif
  126.     close_story ();
  127.  
  128.     exit (EXIT_SUCCESS);
  129.  
  130.     return (0);
  131.  
  132. }/* main */
  133.  
  134. #ifdef __STDC__
  135. static void show_header (void)
  136. #else
  137. static void show_header ()
  138. #endif
  139. {
  140.  
  141.     printf ("Game type = %d", (int) get_byte (H_TYPE));
  142.     printf (", conf. info. = %x", (unsigned int) get_byte (H_CONFIG));
  143.     printf (", version = %d", (int) get_word (H_VERSION));
  144.     printf (", date = %c%c/%c%c/%c%c\n",
  145.         (char) get_byte (H_RELEASE_DATE + 4), (char) get_byte (H_RELEASE_DATE + 5),
  146.         (char) get_byte (H_RELEASE_DATE + 2), (char) get_byte (H_RELEASE_DATE + 3),
  147.         (char) get_byte (H_RELEASE_DATE + 0), (char) get_byte (H_RELEASE_DATE + 1));
  148.  
  149. }/* show_header */
  150.  
  151. #ifdef __STDC__
  152. static void show_synonym (void)
  153. #else
  154. static void show_synonym ()
  155. #endif
  156. {
  157.     unsigned long offset, address;
  158.     int i;
  159.  
  160.     offset = (unsigned long) h_synonyms_offset;
  161.     printf ("\nSynonym list address = %lx\n\n", offset);
  162.  
  163.     for (i = 0; i < (3 * 32); i++) {
  164.         address = (unsigned long) read_data_word (&offset) * 2;
  165.         printf ("[%2d] \"", i);
  166.         decode_text (&address);
  167.         printf ("\"\n");
  168.     }
  169.     printf ("\nSynonym list ends at address %lx\n", offset);
  170.  
  171. }/* show_synonym */
  172.  
  173. #ifdef __STDC__
  174. static void show_object (void)
  175. #else
  176. static void show_object ()
  177. #endif
  178. {
  179.     unsigned long offset, object_address, address;
  180.     int object_count, data, i, j, k;
  181.  
  182.     load_words (0x20);
  183.  
  184.     offset = (unsigned long) h_objects_offset;
  185.  
  186.     object_address = (unsigned long) get_object_address (1);
  187.     if (h_type == V3) {
  188.         address = object_address + O3_PROPERTY_OFFSET;
  189.         object_count = ((int) read_data_word (&address) - object_address) / O3_SIZE;
  190.     } else {
  191.         address = object_address + O4_PROPERTY_OFFSET;
  192.         object_count = ((int) read_data_word (&address) - object_address) / O4_SIZE;
  193.     }
  194.  
  195.     printf ("\nObject list address = %lx\n\n", offset);
  196.     printf ("  Object count = %d\n\n", object_count);
  197.  
  198.     for (i = 1; i <= object_count; i++) {
  199.         object_address = (unsigned long) get_object_address ((zword_t) i);
  200.         printf ("[%3d] Attributes:    ", i);
  201.         if (h_type == V3) {
  202.             for (j = 0; j < 4; j++) {
  203.                 data = (int) read_data_byte (&object_address);
  204.                 for (k = 7; k >= 0; k--)
  205.                     printf ("%01d", (data >> k) & 1);
  206.                 printf (" ");
  207.             }
  208.             printf ("\n");
  209.             printf ("      Parent object: %3d", (int) read_data_byte (&object_address));
  210.             printf ("  Next object: %3d", (int) read_data_byte (&object_address));
  211.             printf ("  Child object: %3d\n", (int) read_data_byte (&object_address));
  212.         } else {
  213.             for (j = 0; j < 6; j++) {
  214.                 data = (int) read_data_byte (&object_address);
  215.                 for (k = 7; k >= 0; k--)
  216.                     printf ("%01d", (data >> k) & 1);
  217.                 printf (" ");
  218.             }
  219.             printf ("\n");
  220.             printf ("      Parent object: %3d", (int) read_data_word (&object_address));
  221.             printf ("  Next object: %3d", (int) read_data_word (&object_address));
  222.             printf ("  Child object: %3d\n", (int) read_data_word (&object_address));
  223.         }
  224.         address = (unsigned long) read_data_word (&object_address);
  225.         printf ("      Property offset: %04lx\n", address);
  226.         printf ("          Description: \"");
  227.         if (read_data_byte (&address))
  228.             decode_text (&address);
  229.         printf ("\"\n");
  230.         printf ("          Properties:\n");
  231.         print_property_list (&address, i);
  232.         printf ("\n");
  233.     }
  234.  
  235.     printf ("\nObject list ends at address = %lx\n", address);
  236.  
  237.     free_words ();
  238.  
  239. }/* show_object */
  240.  
  241. #ifdef __STDC__
  242. static void print_property_list (unsigned long *address, int obj)
  243. #else
  244. static void print_property_list (address, obj)
  245. unsigned long *address;
  246. int obj;
  247. #endif
  248. {
  249.     int data, count;
  250.  
  251.     while (data = (int) read_data_byte (address)) {
  252.         printf ("              [%2d] ", data & property_mask);
  253.         if (h_type == V3)
  254.             count = ((data & property_size_mask) >> 5) + 1;
  255.         else if (data & 0x80)
  256.             count = read_data_byte (address) & property_size_mask;
  257.         else if (data & 0x40)
  258.             count = 2;
  259.         else
  260.             count = 1;
  261. #ifdef ZORKI /* Only works for ZorkI, other games long description, etc. vary */
  262.         if (print_property_values (obj, data, count, address))
  263. #endif
  264.         while (count--)
  265.             printf ("%02x ", (unsigned int) read_data_byte (address));
  266.         printf ("\n");
  267.     }
  268.  
  269. }/* print_property_list */
  270. #ifdef ZORKI
  271. #ifdef __STDC__
  272. static int print_property_values (int obj, int property, int plen, unsigned long *address)
  273. #else
  274. static int print_property_values (obj, property, plen, address)
  275. int obj, property, plen;
  276. unsigned long *address;
  277. #endif
  278. {
  279.     unsigned long offset;
  280.     int i;
  281.     wentry_t *wentry;
  282.  
  283.     static const char *directions[] = {
  284.         "Land", "Out", "In", "Down", "Up",
  285.         "Southwest", "Southeast", "Northwest", "Northeast",
  286.         "South", "West", "East", "North"};
  287.  
  288.     property &= property_mask;
  289.     switch (property) {
  290.         case 31: case 30: case 29: case 28: case 27: case 26:
  291.         case 25: case 24: case 23: case 22: case 21: case 20: case 19:
  292.             printf ("%s: ", directions[property - 19]);
  293.             switch (plen) {
  294.                 case 1:
  295.                     print_object_desc ((int) read_data_byte (address));
  296.                     break;
  297.                 case 2:
  298.                     offset = (unsigned long) read_data_word (address) * story_scaler;
  299.                     print_string (&offset);
  300.                     break;
  301.                 case 3:
  302.                     offset = (unsigned long) read_data_word (address) * story_scaler;
  303.                     printf ("action routine: %lx", offset);
  304.                     read_data_byte (address);
  305.                     break;
  306.                 case 4:
  307.                     print_object_desc ((int) read_data_byte (address));
  308.                     printf (" if ");
  309.                     i = (int) read_data_byte (address);
  310.                     if (i == 0)
  311.                         printf ("(SP)+");
  312.                     else
  313.                         if (i < 16)
  314.                             printf ("L%02x", i - 1);
  315.                         else
  316.                             printf ("G%02x", i - 16);
  317.                     printf (" != 0 else ");
  318.                     offset = (unsigned long) read_data_word (address) * story_scaler;
  319.                     if (offset)
  320.                         print_string (&offset);
  321.                     else
  322.                         printf ("\"You can't go that way.\"");
  323.                     break;
  324.                 case 5:
  325.                     print_object_desc ((int) read_data_byte (address));
  326.                     printf (" ");
  327.                     i = (int) read_data_byte (address);
  328.                     offset = (unsigned long) read_data_word (address) * story_scaler;
  329.                     if (offset)
  330.                         print_string (&offset);
  331.                     else {
  332.                         printf ("else \"The ");
  333.                         print_object_desc (i);
  334.                         printf (" is closed.\"");
  335.                     }
  336.                     read_data_byte (address);
  337.                     break;
  338.                 default:
  339.                     return (1);
  340.             }
  341.             break;
  342.         case 18:
  343.             printf ("Names: ");
  344.             for (i = 0; i < (plen / 2); i++) {
  345.                 offset = (unsigned long) read_data_word (address);
  346.                 print_string (&offset);
  347.                 printf (" ");
  348.             }
  349.             break;
  350.         case 17:
  351.             printf ("Action routine: %lx", (unsigned long) read_data_word (address));
  352.             break;
  353.         case 16:
  354.             printf ("Adjectives: ");
  355.             while (plen--) {
  356.                 i = (int) read_data_byte (address);
  357.                 wentry = lookup_word (NULL, i);
  358.                 if (wentry != NULL) {
  359.                     offset = wentry->text;
  360.                     print_string (&offset);
  361.                 } else
  362.                     printf ("[%02x]", i);
  363.                 printf (" ");
  364.             }
  365.             break;
  366.         case 15:
  367.             printf ("Weight: %d", (int) read_data_word (address));
  368.             break;
  369.         case 14:
  370.             printf ("Initial description: ");
  371.             offset = (unsigned long) read_data_word (address) * story_scaler;
  372.             print_string (&offset);
  373.             break;
  374.         case 13:
  375.             printf ("Find score: %d", (int) read_data_word (address));
  376.             break;
  377.         case 12:
  378.             printf ("Return score: %d", (int) read_data_word (address));
  379.             break;
  380.         case 11:
  381.             printf ("Long description: ");
  382.             offset = (unsigned long) read_data_word (address) * story_scaler;
  383.             print_string (&offset);
  384.             break;
  385.         case 10:
  386.             printf ("Hold capacity: %d", (int) read_data_word (address));
  387.             break;
  388.         case 9:
  389.             printf ("Routine: %lx", (unsigned long) read_data_word (address) * story_scaler);
  390.             break;
  391.         case 8:
  392.             printf ("Read description: ");
  393.             offset = (unsigned long) read_data_word (address) * story_scaler;
  394.             print_string (&offset);
  395.             break;
  396.         case 7:
  397.             printf ("Wait time: %d", (int) read_data_word (address));
  398.             break;
  399.         case 6:
  400.             printf ("Vehicle attribute: %d", (int) read_data_word (address));
  401.             break;
  402.         case 5:
  403.             printf ("Referenced objects: ");
  404.             while (plen--) {
  405.                 print_object_desc ((int) read_data_byte (address));
  406.                 printf (" ");
  407.             }
  408.             break;
  409.         case 4:
  410.             printf ("Word action routines: ");
  411.             for (i = 0; i < (plen / 4); i++) {
  412.                 offset = (unsigned long) read_data_word (address);
  413.                 print_string (&offset);
  414.                 printf (" = %lx ", (unsigned long) read_data_word (address) * story_scaler);
  415.             }
  416.             break;
  417.         case 3:
  418.             printf ("Spare1: %d", (int) read_data_word (address));
  419.             break;
  420.         case 2:
  421.             printf ("Spare2: %d", (int) read_data_word (address));
  422.             break;
  423.         default:
  424.             return (1);
  425.     }
  426.  
  427.     return (0);
  428.  
  429. }/* print_property_values */
  430.  
  431. #ifdef __STDC__
  432. static void print_string (unsigned long *address)
  433. #else
  434. static void print_string (address)
  435. unsigned long *address;
  436. #endif
  437. {
  438.  
  439.     printf ("\"");
  440.     decode_text (address);
  441.     printf ("\"");
  442.  
  443. }/* print_string */
  444. #endif /* ZORKI */
  445. #ifdef __STDC__
  446. static void show_tree (void)
  447. #else
  448. static void show_tree ()
  449. #endif
  450. {
  451.     unsigned long object_address, address;
  452.     int object_count, i;
  453.     unsigned int parent;
  454.  
  455.     object_address = (unsigned long) get_object_address (1);
  456.     if (h_type == V3) {
  457.         address = object_address + O3_PROPERTY_OFFSET;
  458.         object_count = ((int) read_data_word (&address) - object_address) / O3_SIZE;
  459.     } else {
  460.         address = object_address + O4_PROPERTY_OFFSET;
  461.         object_count = ((int) read_data_word (&address) - object_address) / O4_SIZE;
  462.     }
  463.  
  464.     printf ("\nObject tree \n\n");
  465.  
  466.     for (i = 1; i <= object_count; i++) {
  467.         object_address = (unsigned long) get_object_address ((zword_t) i);
  468.         if (h_type == V3) {
  469.             object_address += O3_PARENT;
  470.             parent = (int) read_data_byte (&object_address);
  471.         } else {
  472.             object_address += O4_PARENT;
  473.             parent = (unsigned int) read_data_word (&object_address);
  474.         }
  475.         if (parent == 0)
  476.             print_object (i, 0);
  477.     }
  478.  
  479. }/* show_tree */
  480.  
  481. #ifdef __STDC__
  482. static void print_object (int obj, int depth)
  483. #else
  484. static void print_object (obj, depth)
  485. int obj;
  486. int depth;
  487. #endif
  488. {
  489.     unsigned long object_address, address;
  490.     int child, i;
  491.  
  492.     while (obj) {
  493.         for (i = 0; i < depth; i++)
  494.             printf (" . ");
  495.         printf ("[%3d] ", obj);
  496.         print_object_desc (obj);
  497.         printf ("\n");
  498.         object_address = (unsigned long) get_object_address ((zword_t) obj);
  499.         if (h_type == V3) {
  500.             address = object_address + O3_CHILD;
  501.             child = (int) read_data_byte (&address);
  502.             address = object_address + O3_NEXT;
  503.             obj = (int) read_data_byte (&address);
  504.         } else {
  505.             address = object_address + O4_CHILD;
  506.             child = (int) read_data_word (&address);
  507.             address = object_address + O4_NEXT;
  508.             obj = (unsigned int) read_data_word (&address);
  509.         }
  510.         if (child)
  511.             print_object (child, depth + 1);
  512.     }
  513.  
  514. }/* print_object */
  515.  
  516. #ifdef __STDC__
  517. static void print_object_desc (int obj)
  518. #else
  519. static void print_object_desc (obj)
  520. int obj;
  521. #endif
  522. {
  523.     unsigned long object_address, address;
  524.  
  525.     printf ("\"");
  526.     if (obj) {
  527.         object_address = (unsigned long) get_object_address ((zword_t) obj);
  528.         if (h_type == V3)
  529.             address = object_address + O3_PROPERTY_OFFSET;
  530.         else
  531.             address = object_address + O4_PROPERTY_OFFSET;
  532.         address = (unsigned long) read_data_word (&address);
  533.         if (read_data_byte (&address))
  534.             decode_text (&address);
  535.     }
  536.     printf ("\"");
  537.  
  538. }/* print_object_desc */
  539. #ifndef ONE_COLUMN
  540. #ifdef __STDC__
  541. static void show_dictionary (void)
  542. #else
  543. static void show_dictionary ()
  544. #endif
  545. {
  546.     unsigned long offset, address;
  547.     int separator_count, word_size, word_count, columns, i, length;
  548.  
  549.     offset = (unsigned long) h_words_offset;
  550.     printf ("\nDictionary header address = %lx\n\n", offset);
  551.     separator_count = (int) read_data_byte (&offset);
  552.     printf ("  Word separators = \"");
  553.     for (; separator_count; separator_count--)
  554.         printf ("%c", (char) read_data_byte (&offset));
  555.     printf ("\"\n");
  556.     word_size = (int) read_data_byte (&offset);
  557.     word_count = (int) read_data_word (&offset);
  558.     printf ("  Word count = %d, word size = %d\n", word_count, word_size);
  559.     printf ("\nDictionary header ends at address = %lx\n", offset);
  560.  
  561.     printf ("\nDictionary address = %lx\n", offset);
  562.  
  563.     columns = 80 / (word_size + 8);
  564.  
  565.     for (i = 1; i <= word_count; i++) {
  566.         if (i % columns == 1)
  567.             printf ("\n");
  568.         printf ("[%4d] ", i);
  569.         address = offset;
  570.         for (length = decode_text (&address); length <= word_size; length++)
  571.             printf (" ");
  572.         offset += word_size;
  573.     }
  574.     printf ("\n\nDictionary ends at address %lx\n", address);
  575.  
  576. }/* show_dictionary */
  577. #else /* ONE_COLUMN */
  578. #ifdef __STDC__
  579. static void show_dictionary2 (void)
  580. #else
  581. static void show_dictionary2 ()
  582. #endif
  583. {
  584.     unsigned long offset, address;
  585.     int separator_count, word_size, word_count, data, i, j, length;
  586.  
  587.     offset = (unsigned long) h_words_offset;
  588.     printf ("\nDictionary header address = %lx\n\n", offset);
  589.     separator_count = (int) read_data_byte (&offset);
  590.     printf ("  Word separators = \"");
  591.     for (; separator_count; separator_count--)
  592.         printf ("%c", (char) read_data_byte (&offset));
  593.     printf ("\"\n");
  594.     word_size = (int) read_data_byte (&offset);
  595.     word_count = (int) read_data_word (&offset);
  596.     printf ("  Word count = %d, word size = %d\n", word_count, word_size);
  597.     printf ("\nDictionary header ends at address = %lx\n", offset);
  598.  
  599.     printf ("\nDictionary address = %lx\n\n", offset);
  600.  
  601.     for (i = 1; i <= word_count; i++) {
  602.         printf ("[%4d] ", i);
  603.         address = offset;
  604.         offset += word_size;
  605.         for (length = decode_text (&address); length <= word_size; length++)
  606.             printf (" ");
  607.         data = (zbyte_t) read_data_byte (&address);
  608.         printf ("[%02x](", data);
  609.         for (j = 7; j >= 0; j--)
  610.             printf ("%01d", (data >> j) & 1);
  611.         printf (")");
  612.         while (address < offset)
  613.             printf ("[%02x]", (int) read_data_byte (&address));
  614.         printf ("\n");
  615.     }
  616.     printf ("\nDictionary ends at address %lx\n", offset);
  617.  
  618. }/* show_dictionary2 */
  619. #endif /* ONE_COLUMN */
  620. #ifdef __STDC__
  621. static zword_t get_object_address (zword_t obj)
  622. #else
  623. static zword_t get_object_address (obj)
  624. zword_t obj;
  625. #endif
  626. {
  627.     int offset;
  628.  
  629.     if (h_type == V3)
  630.         offset = h_objects_offset + ((P3_MAX_PROPERTIES - 1) * 2) + ((obj - 1) * O3_SIZE);
  631.     else
  632.         offset = h_objects_offset + ((P4_MAX_PROPERTIES - 1) * 2) + ((obj - 1) * O4_SIZE);
  633.  
  634.     return ((zword_t) offset);
  635.  
  636. }/* get_object_address */
  637.  
  638. #ifdef __STDC__
  639. static void show_verb_table (void)
  640. #else
  641. static void show_verb_table ()
  642. #endif
  643. {
  644.     unsigned long offset, address, address1, address2, text_addr;
  645.     int verb_count, count, max_action = 0, flag, i, j, t;
  646.     int table_type, verb_size;
  647.     int verb_table[256];
  648.     wentry_t *wentry;
  649.  
  650.     load_words (0x40);
  651.  
  652.     offset = (unsigned long) h_restart_size;
  653.     printf ("\nVerb parse table address %lx\n\n", offset);
  654.     address = (unsigned long) read_data_word (&offset);
  655.     offset = (unsigned long) h_restart_size;
  656.     verb_count = (int) ((address - offset) / 2);
  657.     printf ("  Verb entries = %d\n\n", verb_count);
  658.  
  659.     address = offset;
  660.     address1 = (unsigned long) read_data_word (&offset);
  661.     address2 = (unsigned long) read_data_word (&offset);
  662.     count = (int) read_data_byte (&address1);
  663.     offset = address;
  664.     verb_size = (address2 - address1) / count;
  665.  
  666.     if (h_type == V3 || h_type == V4) {
  667.         table_type = 0;
  668.         verb_size = 8;
  669.     } else {
  670.         if (verb_size == 8)
  671.             table_type = 0;
  672.         else
  673.             table_type = 1;
  674.     }
  675.  
  676.     for (i = 0; i < verb_count; i++) {
  677.         address = (unsigned long) read_data_word (&offset);
  678.         count = (int) read_data_byte (&address);
  679.         flag = 1;
  680.         printf ("[%2x] (%2d) ", 255 - i, count);
  681.         while (count--) {
  682.             printf ("[");
  683.             t = (int) read_data_byte (&address);
  684.             printf ("%02x ", t);
  685.             if (table_type) {
  686.                 t = (t >> 6) & 0x03;
  687.                 if (t == 0)
  688.                     verb_size = 2;
  689.                 else if (t == 1)
  690.                     verb_size = 4;
  691.                 else
  692.                     verb_size = 7;
  693.             }
  694.             for (j = 1; j < verb_size; j++) {
  695.                 t = (int) read_data_byte (&address);
  696.                 printf ("%02x", t);
  697.                 if ((table_type && j == 1) || (table_type == 0 && j == 7)) {
  698.                     if (t > max_action)
  699.                         max_action = t;
  700.                     verb_table[t] = 255 - i;
  701.                 }
  702.                 if (j < (verb_size - 1))
  703.                     printf (" ");
  704.             }
  705.             printf ("]");
  706.             for (j = verb_size; j < 8; j++)
  707.                 printf ("   ");
  708.             if (flag) {
  709.                 flag = 0;
  710.                 wentry = lookup_word (NULL, 255 - i);
  711.                 if (wentry != NULL) {
  712.                     do {
  713.                         text_addr = (unsigned long) wentry->text;
  714.                         printf (" \"");
  715.                         decode_text (&text_addr);
  716.                         printf ("\"");
  717.                     } while ((wentry = lookup_word (wentry, 255 - i)) != NULL);
  718.                 } else
  719.                     printf (" no verb");
  720.             }
  721.             printf ("\n");
  722.             if (count)
  723.                 printf ("          ");
  724.         }
  725.     }
  726.     while (read_data_byte (&address) == 0)
  727.         ;
  728.     offset = address - 1;
  729.     printf ("\nVerb parse table ends at address %lx\n", offset);
  730.  
  731.     max_action++;
  732.  
  733.     printf ("\nVerb action table address %lx\n\n", offset);
  734.     printf ("  Action table entries = %d\n\n", max_action);
  735.     for (i = 0; i < max_action; i++) {
  736.         printf ("[%3d] %5x", i, (int) read_data_word (&offset) * story_scaler);
  737.         wentry = lookup_word (NULL, verb_table[i]);
  738.         if (wentry != NULL) {
  739.             do {
  740.                 text_addr = (unsigned long) wentry->text;
  741.                 printf (" \"");
  742.                 decode_text (&text_addr);
  743.                 printf ("\"");
  744.             } while ((wentry = lookup_word (wentry, verb_table[i])) != NULL);
  745.         } else
  746.             printf (" no verb");
  747.         printf ("\n");
  748.     }
  749.     printf ("\nVerb action table ends at address %lx\n", offset);
  750.  
  751.     printf ("\nVerb pre-action table address %lx\n\n", offset);
  752.     printf ("  Pre-action table entries = %d\n\n", max_action);
  753.     for (i = 0; i < max_action; i++) {
  754.         printf ("[%3d] %5x", i, (int) read_data_word (&offset) * story_scaler);
  755.         wentry = lookup_word (NULL, verb_table[i]);
  756.         if (wentry != NULL) {
  757.             do {
  758.                 text_addr = (unsigned long) wentry->text;
  759.                 printf (" \"");
  760.                 decode_text (&text_addr);
  761.                 printf ("\"");
  762.             } while ((wentry = lookup_word (wentry, verb_table[i])) != NULL);
  763.         } else
  764.             printf (" no verb");
  765.         printf ("\n");
  766.     }
  767.     printf ("\nVerb pre-action table ends at address %lx\n", offset);
  768.  
  769.     printf ("\nAdjective table address %lx\n\n", offset);
  770.     count = (int) read_data_word (&offset);
  771.     printf ("  Table entries = %d\n\n", count);
  772.     for (i = 0; i < count; i++) {
  773.         address = (int) read_data_word (&offset);
  774.         if (table_type == 0)
  775.             printf ("[%2x] \"", (int) read_data_word (&offset));
  776.         else
  777.             printf ("[%2x] \"", (int) read_data_byte (&offset));
  778.         decode_text (&address);
  779.         printf ("\"\n");
  780.     }
  781.     printf ("\nAdjective table ends at address %lx\n", offset);
  782.  
  783.     free_words ();
  784.  
  785. }/* show_verb_table */
  786.  
  787. #ifdef __STDC__
  788. static void load_words (int mask)
  789. #else
  790. static void load_words (mask)
  791. int mask;
  792. #endif
  793. {
  794.     unsigned long offset, address;
  795.     int word_count, word_size, flags, i;
  796.     wentry_t *wentry;
  797.  
  798.     offset = (unsigned long) h_words_offset;
  799.     offset += (unsigned long) read_data_byte (&offset);
  800.     word_size = (int) read_data_byte (&offset);
  801.     word_count = (int) read_data_word (&offset);
  802.     for (i = 0; i < word_count; i++) {
  803.         address = offset;
  804.         if (h_type == V3)
  805.             address += 4;
  806.         else
  807.             address += 6;
  808.         if ((flags = read_data_byte (&address)) & mask) {
  809.             if ((wentry = (wentry_t *) malloc (sizeof (wentry_t))) == NULL) {
  810.                 fprintf (stderr, "Insufficient memory!\n");
  811.                 exit (EXIT_FAILURE);
  812.             }
  813.             wentry->text = (unsigned short) offset;
  814.             wentry->number = (int) read_data_byte (&address);
  815.             if (((mask == 0x40) && (flags & 0x01) == 0) ||
  816.                 ((mask == 0x20) && (flags & 0x02) == 0))
  817.                 wentry->number = (int) read_data_byte (&address);
  818.             wentry->flink = wentry_head;
  819.             wentry_head = wentry;
  820.         }
  821.         offset += word_size;
  822.     }
  823.  
  824. }/* load_words */
  825.  
  826. #ifdef __STDC__
  827. static wentry_t *lookup_word (wentry_t *wentry, int number)
  828. #else
  829. static wentry_t *lookup_word (wentry, number)
  830. wentry_t *wentry;
  831. int number;
  832. #endif
  833. {
  834.     wentry_t *ptr;
  835.  
  836.     for (ptr = (wentry == NULL) ? wentry_head : wentry->flink;
  837.          ptr != NULL && ptr->number != number;
  838.          ptr = ptr->flink)
  839.         ;
  840.  
  841.     return (ptr);
  842.  
  843. }/* lookup_word */
  844.  
  845. #ifdef __STDC__
  846. static void free_words (void)
  847. #else
  848. static void free_words ()
  849. #endif
  850. {
  851.     wentry_t *ptr, *next_ptr;
  852.  
  853.     for (ptr = wentry_head; ptr != NULL; ptr = next_ptr) {
  854.         next_ptr = ptr->flink;
  855.         free (ptr);
  856.     }
  857.     wentry_head = NULL;
  858.  
  859. }/* free_words */
  860.  
  861. #ifdef __STDC__
  862. static void fix_dictionary (void)
  863. #else
  864. static void fix_dictionary ()
  865. #endif
  866. {
  867.     unsigned long offset;
  868.     int separator_count, word_size, word_count, i;
  869.  
  870.     offset = (unsigned long) h_words_offset;
  871.     separator_count = (int) read_data_byte (&offset);
  872.     offset += separator_count;
  873.     word_size = (int) read_data_byte (&offset);
  874.     word_count = (int) read_data_word (&offset);
  875.  
  876.     for (i = 1; i <= word_count; i++) {
  877.         if ((offset + 4) < (unsigned long) h_data_size)
  878.             if (h_type == V3)
  879.                 set_byte (offset + 2, get_byte (offset + 2) | 0x80);
  880.             else
  881.                 set_byte (offset + 4, get_byte (offset + 4) | 0x80);
  882.         offset += word_size;
  883.     }
  884.  
  885. }/* fix_dictionary */
  886.