home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Elysian Archive
/
AmigaElysianArchive.iso
/
games
/
utils
/
ztools.lha
/
ztools
/
src
/
infodump.c
next >
Wrap
C/C++ Source or Header
|
1992-12-17
|
27KB
|
886 lines
/* infodump.c V1.2
*
* Infocom dictionary dumper, etc. for type 3, 4, 5 and 6 games. If you have
* Zork I then by defining ZORKI you will get a detailed list of object
* properties. Properties numbers and use vary between games so this only works
* for ZORK I.
*
* Requires txio.c and tx.h
*
* Usage: infodump story-file-name
*
* Mark Howell 28 August 1992 howell_ma@movies.enet.dec.com
*
* History:
* Fix verb table display for later type 4 and 5 games
* Fix property list
*/
#include "tx.h"
typedef struct wentry {
struct wentry *flink;
unsigned short text;
int number;
} wentry_t;
#ifdef __STDC__
static void show_header (void);
static void show_synonym (void);
static void show_object (void);
static void print_property_list (unsigned long *, int);
#ifdef ZORKI
static int print_property_values (int, int, int, unsigned long *);
static void print_string (unsigned long *);
#endif
static void show_tree (void);
static void print_object (int, int);
static void print_object_desc (int);
#ifndef ONE_COLUMN
static void show_dictionary (void);
#else
static void show_dictionary2 (void);
#endif
static zword_t get_object_address (zword_t);
static void show_verb_table (void);
static void load_words (int);
static wentry_t *lookup_word (wentry_t *, int);
static void free_words (void);
static void fix_dictionary (void);
#else
static void show_header ();
static void show_synonym ();
static void show_object ();
static void print_property_list ();
#ifdef ZORKI
static int print_property_values ();
static void print_string ();
#endif
static void show_tree ();
static void print_object ();
static void print_object_desc ();
#ifndef ONE_COLUMN
static void show_dictionary ();
#else
static void show_dictionary2 ();
#endif
static zword_t get_object_address ();
static void show_verb_table ();
static void load_words ();
static wentry_t *lookup_word ();
static void free_words ();
static void fix_dictionary ();
#endif
static char alternate_alphabet[3][26];
static wentry_t *wentry_head = NULL;
#ifdef __STDC__
int main (int argc, char *argv [])
#else
int main (argc, argv)
int argc;
char *argv[];
#endif
{
if (argc != 2) {
fprintf (stderr, "Usage: %s story-file\n", argv [0]);
exit (EXIT_FAILURE);
}
open_story (argv [1]);
configure (V3, V6);
load_cache ();
if (h_type == V6 && h_alternate_alphabet_offset) {
unsigned long offset;
int i, j;
offset = (unsigned long) h_alternate_alphabet_offset;
for (i = 0; i < 3; i++) {
for (j = 0; j < 26; j++)
alternate_alphabet[i][j] = read_data_byte (&offset);
lookup_table[i] = &alternate_alphabet[i][0];
}
}
fix_dictionary ();
show_header ();
show_synonym ();
show_object ();
show_tree ();
if (h_type != V6) /* Doesn't work for type 6 games yet */
show_verb_table ();
#ifndef ONE_COLUMN
show_dictionary ();
#else
show_dictionary2 ();
#endif
close_story ();
exit (EXIT_SUCCESS);
return (0);
}/* main */
#ifdef __STDC__
static void show_header (void)
#else
static void show_header ()
#endif
{
printf ("Game type = %d", (int) get_byte (H_TYPE));
printf (", conf. info. = %x", (unsigned int) get_byte (H_CONFIG));
printf (", version = %d", (int) get_word (H_VERSION));
printf (", date = %c%c/%c%c/%c%c\n",
(char) get_byte (H_RELEASE_DATE + 4), (char) get_byte (H_RELEASE_DATE + 5),
(char) get_byte (H_RELEASE_DATE + 2), (char) get_byte (H_RELEASE_DATE + 3),
(char) get_byte (H_RELEASE_DATE + 0), (char) get_byte (H_RELEASE_DATE + 1));
}/* show_header */
#ifdef __STDC__
static void show_synonym (void)
#else
static void show_synonym ()
#endif
{
unsigned long offset, address;
int i;
offset = (unsigned long) h_synonyms_offset;
printf ("\nSynonym list address = %lx\n\n", offset);
for (i = 0; i < (3 * 32); i++) {
address = (unsigned long) read_data_word (&offset) * 2;
printf ("[%2d] \"", i);
decode_text (&address);
printf ("\"\n");
}
printf ("\nSynonym list ends at address %lx\n", offset);
}/* show_synonym */
#ifdef __STDC__
static void show_object (void)
#else
static void show_object ()
#endif
{
unsigned long offset, object_address, address;
int object_count, data, i, j, k;
load_words (0x20);
offset = (unsigned long) h_objects_offset;
object_address = (unsigned long) get_object_address (1);
if (h_type == V3) {
address = object_address + O3_PROPERTY_OFFSET;
object_count = ((int) read_data_word (&address) - object_address) / O3_SIZE;
} else {
address = object_address + O4_PROPERTY_OFFSET;
object_count = ((int) read_data_word (&address) - object_address) / O4_SIZE;
}
printf ("\nObject list address = %lx\n\n", offset);
printf (" Object count = %d\n\n", object_count);
for (i = 1; i <= object_count; i++) {
object_address = (unsigned long) get_object_address ((zword_t) i);
printf ("[%3d] Attributes: ", i);
if (h_type == V3) {
for (j = 0; j < 4; j++) {
data = (int) read_data_byte (&object_address);
for (k = 7; k >= 0; k--)
printf ("%01d", (data >> k) & 1);
printf (" ");
}
printf ("\n");
printf (" Parent object: %3d", (int) read_data_byte (&object_address));
printf (" Next object: %3d", (int) read_data_byte (&object_address));
printf (" Child object: %3d\n", (int) read_data_byte (&object_address));
} else {
for (j = 0; j < 6; j++) {
data = (int) read_data_byte (&object_address);
for (k = 7; k >= 0; k--)
printf ("%01d", (data >> k) & 1);
printf (" ");
}
printf ("\n");
printf (" Parent object: %3d", (int) read_data_word (&object_address));
printf (" Next object: %3d", (int) read_data_word (&object_address));
printf (" Child object: %3d\n", (int) read_data_word (&object_address));
}
address = (unsigned long) read_data_word (&object_address);
printf (" Property offset: %04lx\n", address);
printf (" Description: \"");
if (read_data_byte (&address))
decode_text (&address);
printf ("\"\n");
printf (" Properties:\n");
print_property_list (&address, i);
printf ("\n");
}
printf ("\nObject list ends at address = %lx\n", address);
free_words ();
}/* show_object */
#ifdef __STDC__
static void print_property_list (unsigned long *address, int obj)
#else
static void print_property_list (address, obj)
unsigned long *address;
int obj;
#endif
{
int data, count;
while (data = (int) read_data_byte (address)) {
printf (" [%2d] ", data & property_mask);
if (h_type == V3)
count = ((data & property_size_mask) >> 5) + 1;
else if (data & 0x80)
count = read_data_byte (address) & property_size_mask;
else if (data & 0x40)
count = 2;
else
count = 1;
#ifdef ZORKI /* Only works for ZorkI, other games long description, etc. vary */
if (print_property_values (obj, data, count, address))
#endif
while (count--)
printf ("%02x ", (unsigned int) read_data_byte (address));
printf ("\n");
}
}/* print_property_list */
#ifdef ZORKI
#ifdef __STDC__
static int print_property_values (int obj, int property, int plen, unsigned long *address)
#else
static int print_property_values (obj, property, plen, address)
int obj, property, plen;
unsigned long *address;
#endif
{
unsigned long offset;
int i;
wentry_t *wentry;
static const char *directions[] = {
"Land", "Out", "In", "Down", "Up",
"Southwest", "Southeast", "Northwest", "Northeast",
"South", "West", "East", "North"};
property &= property_mask;
switch (property) {
case 31: case 30: case 29: case 28: case 27: case 26:
case 25: case 24: case 23: case 22: case 21: case 20: case 19:
printf ("%s: ", directions[property - 19]);
switch (plen) {
case 1:
print_object_desc ((int) read_data_byte (address));
break;
case 2:
offset = (unsigned long) read_data_word (address) * story_scaler;
print_string (&offset);
break;
case 3:
offset = (unsigned long) read_data_word (address) * story_scaler;
printf ("action routine: %lx", offset);
read_data_byte (address);
break;
case 4:
print_object_desc ((int) read_data_byte (address));
printf (" if ");
i = (int) read_data_byte (address);
if (i == 0)
printf ("(SP)+");
else
if (i < 16)
printf ("L%02x", i - 1);
else
printf ("G%02x", i - 16);
printf (" != 0 else ");
offset = (unsigned long) read_data_word (address) * story_scaler;
if (offset)
print_string (&offset);
else
printf ("\"You can't go that way.\"");
break;
case 5:
print_object_desc ((int) read_data_byte (address));
printf (" ");
i = (int) read_data_byte (address);
offset = (unsigned long) read_data_word (address) * story_scaler;
if (offset)
print_string (&offset);
else {
printf ("else \"The ");
print_object_desc (i);
printf (" is closed.\"");
}
read_data_byte (address);
break;
default:
return (1);
}
break;
case 18:
printf ("Names: ");
for (i = 0; i < (plen / 2); i++) {
offset = (unsigned long) read_data_word (address);
print_string (&offset);
printf (" ");
}
break;
case 17:
printf ("Action routine: %lx", (unsigned long) read_data_word (address));
break;
case 16:
printf ("Adjectives: ");
while (plen--) {
i = (int) read_data_byte (address);
wentry = lookup_word (NULL, i);
if (wentry != NULL) {
offset = wentry->text;
print_string (&offset);
} else
printf ("[%02x]", i);
printf (" ");
}
break;
case 15:
printf ("Weight: %d", (int) read_data_word (address));
break;
case 14:
printf ("Initial description: ");
offset = (unsigned long) read_data_word (address) * story_scaler;
print_string (&offset);
break;
case 13:
printf ("Find score: %d", (int) read_data_word (address));
break;
case 12:
printf ("Return score: %d", (int) read_data_word (address));
break;
case 11:
printf ("Long description: ");
offset = (unsigned long) read_data_word (address) * story_scaler;
print_string (&offset);
break;
case 10:
printf ("Hold capacity: %d", (int) read_data_word (address));
break;
case 9:
printf ("Routine: %lx", (unsigned long) read_data_word (address) * story_scaler);
break;
case 8:
printf ("Read description: ");
offset = (unsigned long) read_data_word (address) * story_scaler;
print_string (&offset);
break;
case 7:
printf ("Wait time: %d", (int) read_data_word (address));
break;
case 6:
printf ("Vehicle attribute: %d", (int) read_data_word (address));
break;
case 5:
printf ("Referenced objects: ");
while (plen--) {
print_object_desc ((int) read_data_byte (address));
printf (" ");
}
break;
case 4:
printf ("Word action routines: ");
for (i = 0; i < (plen / 4); i++) {
offset = (unsigned long) read_data_word (address);
print_string (&offset);
printf (" = %lx ", (unsigned long) read_data_word (address) * story_scaler);
}
break;
case 3:
printf ("Spare1: %d", (int) read_data_word (address));
break;
case 2:
printf ("Spare2: %d", (int) read_data_word (address));
break;
default:
return (1);
}
return (0);
}/* print_property_values */
#ifdef __STDC__
static void print_string (unsigned long *address)
#else
static void print_string (address)
unsigned long *address;
#endif
{
printf ("\"");
decode_text (address);
printf ("\"");
}/* print_string */
#endif /* ZORKI */
#ifdef __STDC__
static void show_tree (void)
#else
static void show_tree ()
#endif
{
unsigned long object_address, address;
int object_count, i;
unsigned int parent;
object_address = (unsigned long) get_object_address (1);
if (h_type == V3) {
address = object_address + O3_PROPERTY_OFFSET;
object_count = ((int) read_data_word (&address) - object_address) / O3_SIZE;
} else {
address = object_address + O4_PROPERTY_OFFSET;
object_count = ((int) read_data_word (&address) - object_address) / O4_SIZE;
}
printf ("\nObject tree \n\n");
for (i = 1; i <= object_count; i++) {
object_address = (unsigned long) get_object_address ((zword_t) i);
if (h_type == V3) {
object_address += O3_PARENT;
parent = (int) read_data_byte (&object_address);
} else {
object_address += O4_PARENT;
parent = (unsigned int) read_data_word (&object_address);
}
if (parent == 0)
print_object (i, 0);
}
}/* show_tree */
#ifdef __STDC__
static void print_object (int obj, int depth)
#else
static void print_object (obj, depth)
int obj;
int depth;
#endif
{
unsigned long object_address, address;
int child, i;
while (obj) {
for (i = 0; i < depth; i++)
printf (" . ");
printf ("[%3d] ", obj);
print_object_desc (obj);
printf ("\n");
object_address = (unsigned long) get_object_address ((zword_t) obj);
if (h_type == V3) {
address = object_address + O3_CHILD;
child = (int) read_data_byte (&address);
address = object_address + O3_NEXT;
obj = (int) read_data_byte (&address);
} else {
address = object_address + O4_CHILD;
child = (int) read_data_word (&address);
address = object_address + O4_NEXT;
obj = (unsigned int) read_data_word (&address);
}
if (child)
print_object (child, depth + 1);
}
}/* print_object */
#ifdef __STDC__
static void print_object_desc (int obj)
#else
static void print_object_desc (obj)
int obj;
#endif
{
unsigned long object_address, address;
printf ("\"");
if (obj) {
object_address = (unsigned long) get_object_address ((zword_t) obj);
if (h_type == V3)
address = object_address + O3_PROPERTY_OFFSET;
else
address = object_address + O4_PROPERTY_OFFSET;
address = (unsigned long) read_data_word (&address);
if (read_data_byte (&address))
decode_text (&address);
}
printf ("\"");
}/* print_object_desc */
#ifndef ONE_COLUMN
#ifdef __STDC__
static void show_dictionary (void)
#else
static void show_dictionary ()
#endif
{
unsigned long offset, address;
int separator_count, word_size, word_count, columns, i, length;
offset = (unsigned long) h_words_offset;
printf ("\nDictionary header address = %lx\n\n", offset);
separator_count = (int) read_data_byte (&offset);
printf (" Word separators = \"");
for (; separator_count; separator_count--)
printf ("%c", (char) read_data_byte (&offset));
printf ("\"\n");
word_size = (int) read_data_byte (&offset);
word_count = (int) read_data_word (&offset);
printf (" Word count = %d, word size = %d\n", word_count, word_size);
printf ("\nDictionary header ends at address = %lx\n", offset);
printf ("\nDictionary address = %lx\n", offset);
columns = 80 / (word_size + 8);
for (i = 1; i <= word_count; i++) {
if (i % columns == 1)
printf ("\n");
printf ("[%4d] ", i);
address = offset;
for (length = decode_text (&address); length <= word_size; length++)
printf (" ");
offset += word_size;
}
printf ("\n\nDictionary ends at address %lx\n", address);
}/* show_dictionary */
#else /* ONE_COLUMN */
#ifdef __STDC__
static void show_dictionary2 (void)
#else
static void show_dictionary2 ()
#endif
{
unsigned long offset, address;
int separator_count, word_size, word_count, data, i, j, length;
offset = (unsigned long) h_words_offset;
printf ("\nDictionary header address = %lx\n\n", offset);
separator_count = (int) read_data_byte (&offset);
printf (" Word separators = \"");
for (; separator_count; separator_count--)
printf ("%c", (char) read_data_byte (&offset));
printf ("\"\n");
word_size = (int) read_data_byte (&offset);
word_count = (int) read_data_word (&offset);
printf (" Word count = %d, word size = %d\n", word_count, word_size);
printf ("\nDictionary header ends at address = %lx\n", offset);
printf ("\nDictionary address = %lx\n\n", offset);
for (i = 1; i <= word_count; i++) {
printf ("[%4d] ", i);
address = offset;
offset += word_size;
for (length = decode_text (&address); length <= word_size; length++)
printf (" ");
data = (zbyte_t) read_data_byte (&address);
printf ("[%02x](", data);
for (j = 7; j >= 0; j--)
printf ("%01d", (data >> j) & 1);
printf (")");
while (address < offset)
printf ("[%02x]", (int) read_data_byte (&address));
printf ("\n");
}
printf ("\nDictionary ends at address %lx\n", offset);
}/* show_dictionary2 */
#endif /* ONE_COLUMN */
#ifdef __STDC__
static zword_t get_object_address (zword_t obj)
#else
static zword_t get_object_address (obj)
zword_t obj;
#endif
{
int offset;
if (h_type == V3)
offset = h_objects_offset + ((P3_MAX_PROPERTIES - 1) * 2) + ((obj - 1) * O3_SIZE);
else
offset = h_objects_offset + ((P4_MAX_PROPERTIES - 1) * 2) + ((obj - 1) * O4_SIZE);
return ((zword_t) offset);
}/* get_object_address */
#ifdef __STDC__
static void show_verb_table (void)
#else
static void show_verb_table ()
#endif
{
unsigned long offset, address, address1, address2, text_addr;
int verb_count, count, max_action = 0, flag, i, j, t;
int table_type, verb_size;
int verb_table[256];
wentry_t *wentry;
load_words (0x40);
offset = (unsigned long) h_restart_size;
printf ("\nVerb parse table address %lx\n\n", offset);
address = (unsigned long) read_data_word (&offset);
offset = (unsigned long) h_restart_size;
verb_count = (int) ((address - offset) / 2);
printf (" Verb entries = %d\n\n", verb_count);
address = offset;
address1 = (unsigned long) read_data_word (&offset);
address2 = (unsigned long) read_data_word (&offset);
count = (int) read_data_byte (&address1);
offset = address;
verb_size = (address2 - address1) / count;
if (h_type == V3 || h_type == V4) {
table_type = 0;
verb_size = 8;
} else {
if (verb_size == 8)
table_type = 0;
else
table_type = 1;
}
for (i = 0; i < verb_count; i++) {
address = (unsigned long) read_data_word (&offset);
count = (int) read_data_byte (&address);
flag = 1;
printf ("[%2x] (%2d) ", 255 - i, count);
while (count--) {
printf ("[");
t = (int) read_data_byte (&address);
printf ("%02x ", t);
if (table_type) {
t = (t >> 6) & 0x03;
if (t == 0)
verb_size = 2;
else if (t == 1)
verb_size = 4;
else
verb_size = 7;
}
for (j = 1; j < verb_size; j++) {
t = (int) read_data_byte (&address);
printf ("%02x", t);
if ((table_type && j == 1) || (table_type == 0 && j == 7)) {
if (t > max_action)
max_action = t;
verb_table[t] = 255 - i;
}
if (j < (verb_size - 1))
printf (" ");
}
printf ("]");
for (j = verb_size; j < 8; j++)
printf (" ");
if (flag) {
flag = 0;
wentry = lookup_word (NULL, 255 - i);
if (wentry != NULL) {
do {
text_addr = (unsigned long) wentry->text;
printf (" \"");
decode_text (&text_addr);
printf ("\"");
} while ((wentry = lookup_word (wentry, 255 - i)) != NULL);
} else
printf (" no verb");
}
printf ("\n");
if (count)
printf (" ");
}
}
while (read_data_byte (&address) == 0)
;
offset = address - 1;
printf ("\nVerb parse table ends at address %lx\n", offset);
max_action++;
printf ("\nVerb action table address %lx\n\n", offset);
printf (" Action table entries = %d\n\n", max_action);
for (i = 0; i < max_action; i++) {
printf ("[%3d] %5x", i, (int) read_data_word (&offset) * story_scaler);
wentry = lookup_word (NULL, verb_table[i]);
if (wentry != NULL) {
do {
text_addr = (unsigned long) wentry->text;
printf (" \"");
decode_text (&text_addr);
printf ("\"");
} while ((wentry = lookup_word (wentry, verb_table[i])) != NULL);
} else
printf (" no verb");
printf ("\n");
}
printf ("\nVerb action table ends at address %lx\n", offset);
printf ("\nVerb pre-action table address %lx\n\n", offset);
printf (" Pre-action table entries = %d\n\n", max_action);
for (i = 0; i < max_action; i++) {
printf ("[%3d] %5x", i, (int) read_data_word (&offset) * story_scaler);
wentry = lookup_word (NULL, verb_table[i]);
if (wentry != NULL) {
do {
text_addr = (unsigned long) wentry->text;
printf (" \"");
decode_text (&text_addr);
printf ("\"");
} while ((wentry = lookup_word (wentry, verb_table[i])) != NULL);
} else
printf (" no verb");
printf ("\n");
}
printf ("\nVerb pre-action table ends at address %lx\n", offset);
printf ("\nAdjective table address %lx\n\n", offset);
count = (int) read_data_word (&offset);
printf (" Table entries = %d\n\n", count);
for (i = 0; i < count; i++) {
address = (int) read_data_word (&offset);
if (table_type == 0)
printf ("[%2x] \"", (int) read_data_word (&offset));
else
printf ("[%2x] \"", (int) read_data_byte (&offset));
decode_text (&address);
printf ("\"\n");
}
printf ("\nAdjective table ends at address %lx\n", offset);
free_words ();
}/* show_verb_table */
#ifdef __STDC__
static void load_words (int mask)
#else
static void load_words (mask)
int mask;
#endif
{
unsigned long offset, address;
int word_count, word_size, flags, i;
wentry_t *wentry;
offset = (unsigned long) h_words_offset;
offset += (unsigned long) read_data_byte (&offset);
word_size = (int) read_data_byte (&offset);
word_count = (int) read_data_word (&offset);
for (i = 0; i < word_count; i++) {
address = offset;
if (h_type == V3)
address += 4;
else
address += 6;
if ((flags = read_data_byte (&address)) & mask) {
if ((wentry = (wentry_t *) malloc (sizeof (wentry_t))) == NULL) {
fprintf (stderr, "Insufficient memory!\n");
exit (EXIT_FAILURE);
}
wentry->text = (unsigned short) offset;
wentry->number = (int) read_data_byte (&address);
if (((mask == 0x40) && (flags & 0x01) == 0) ||
((mask == 0x20) && (flags & 0x02) == 0))
wentry->number = (int) read_data_byte (&address);
wentry->flink = wentry_head;
wentry_head = wentry;
}
offset += word_size;
}
}/* load_words */
#ifdef __STDC__
static wentry_t *lookup_word (wentry_t *wentry, int number)
#else
static wentry_t *lookup_word (wentry, number)
wentry_t *wentry;
int number;
#endif
{
wentry_t *ptr;
for (ptr = (wentry == NULL) ? wentry_head : wentry->flink;
ptr != NULL && ptr->number != number;
ptr = ptr->flink)
;
return (ptr);
}/* lookup_word */
#ifdef __STDC__
static void free_words (void)
#else
static void free_words ()
#endif
{
wentry_t *ptr, *next_ptr;
for (ptr = wentry_head; ptr != NULL; ptr = next_ptr) {
next_ptr = ptr->flink;
free (ptr);
}
wentry_head = NULL;
}/* free_words */
#ifdef __STDC__
static void fix_dictionary (void)
#else
static void fix_dictionary ()
#endif
{
unsigned long offset;
int separator_count, word_size, word_count, i;
offset = (unsigned long) h_words_offset;
separator_count = (int) read_data_byte (&offset);
offset += separator_count;
word_size = (int) read_data_byte (&offset);
word_count = (int) read_data_word (&offset);
for (i = 1; i <= word_count; i++) {
if ((offset + 4) < (unsigned long) h_data_size)
if (h_type == V3)
set_byte (offset + 2, get_byte (offset + 2) | 0x80);
else
set_byte (offset + 4, get_byte (offset + 4) | 0x80);
offset += word_size;
}
}/* fix_dictionary */