536 lines · 15.7 KB · C
RawDownload
/* * showobj - part of infodump * * Object display routines. */ #include "tx.h" #ifdef __STDC__void configure_object_tables    (unsigned int *, unsigned long *, unsigned long *, unsigned long *,     unsigned long *);static unsigned int get_object_address    (unsigned int);static void print_property_list    (unsigned long *, unsigned long);static void print_object    (int, int);static void print_object_desc    (int);#elsevoid configure_object_tables ();static unsigned int get_object_address ();static void print_property_list ();static void print_object ();static void print_object_desc ();#endif /* * configure_object_tables * * Determine the object table start and end addresses, together with the * property data start and end addresses, and the number of objects. * * Format: * * The object information consists of two parts. Firstly a fixed table of * objects and secondly, an area of variable property data. * * The format of the object varies between game types. For pre-V4 games * the format is: * * struct zobject { *    unsigned short attributes[2]; *    unsigned char parent; *    unsigned char next; *    unsigned char child; *    unsigned short property_offset; * } * * Post-V3 the format is: * * struct zobject { *    unsigned short attributes[3]; *    unsigned short parent; *    unsigned short next; *    unsigned short child; *    unsigned short property_offset; * } * * Attributes are an array of bits that can be tested, set and cleared. The * parent, next and child fields are object numbers. These fields are used to * construct an object tree that represents concepts such as object contains * or room contains. The property offset is the address in the data file of the * start of the property data for the object. Objects are numbered from 1. * Object 0 is used as the NULL object to terminate object lists. * * Note: The start of the object table contains a list of default property * values that are used when a property is not present for an object. The size * of this table in words is the maximum number of properties minus 1. * * The format of the object properties is complex. It is: * * [Common prefix][property n]...[property n][property 0] * * Properties occur in descending order from highest property number to zero. * Property zero always terminates the list, but is not referenced by the Z-code. * Instead, property zero is used to terminate the scan down the property list, if * a property is not defined. This behaviour is required when loading a default * property list item, or to catch setting undefined property values. * * The size information is ignored for property 0, which is actually just specified * as a byte containing 0x00. * * Key: * * (n) = size of block in bytes * max = maximum number of recurring blocks * min = minimum number of recurring blocks * * Common prefix: * *  (1)       (2)          (2) * +-------+ +------+     +------+ * | count | | text | ... | text | max=255, min=0 * +-------+ +------+     +------+ * * count = number of following text blocks * text = object description, encoded * * Property n (V3 format): * *  (1)             (1)          (1) * +--------+----+ +------+     +------+ * | size-1 | id | | data | ... | data | max=8, min=1 * +--------+----+ +------+     +------+ *  7      5 4  0 * * size-1 = size of property - 1 * id = property identifier * data = property data * * Maximum property number = 31 * * Property n (V4 format): * *  (1) Property header byte       (1) Property size byte         (1)          (1) * +-----------+-----------+----+ +-----------+---------+------+ +------+     +------+ * | size byte | word data | id | | size byte | ignored | size | | data | ... | data | max=63, min=0 * +-----------+-----------+----+ +-----------+---------+------+ +------+     +------+ *            7           6 5  0             7         6 5    0 * * size byte = if set then next data block is a the property size byte *             if clear then the 'word data' flag is checked and the property has no size byte * word data = if set then 2 data blocks follow *             if clear 1 data block follows * ignored = this flag is not used by the property manipulation opcodes, it can be set to an arbitary value *           (note: this bit could be used to increase the property size from 63 to 127 bytes) * id = property identifier * size = size of property * data = property data * * Maximum property number = 63 */ #ifdef __STDC__void configure_object_tables (unsigned int *obj_count,                              unsigned long *obj_table_base,                              unsigned long *obj_table_end,                              unsigned long *obj_data_base,                              unsigned long *obj_data_end)#elsevoid configure_object_tables (obj_count,                              obj_table_base,                              obj_table_end,                              obj_data_base,                              obj_data_end)unsigned int *obj_count;unsigned long *obj_table_base;unsigned long *obj_table_end;unsigned long *obj_data_base;unsigned long *obj_data_end;#endif{    unsigned long object_address, address;    unsigned int data_count, data;     *obj_table_base = 0;    *obj_table_end = 0;    *obj_data_base = 0;    *obj_data_end = 0;    *obj_count = 0;     /* The object table address comes from the header */     *obj_table_base = (unsigned long) header.objects;     /* Calculate the number of objects and property addresses range */     do {         /* Count this object and get its address */         (*obj_count)++;        object_address = (unsigned long) get_object_address (*obj_count);         /* Check if we have got to the end of the object list */         if (*obj_data_base == 0 || object_address < *obj_data_base) {             /* Calculate the range of property data */             if ((unsigned int) header.version < V4)                object_address += O3_PROPERTY_OFFSET;            else                object_address += O4_PROPERTY_OFFSET;            address = read_data_word (&object_address);            if (*obj_data_base == 0 || address < *obj_data_base)                *obj_data_base = address;            if (*obj_data_end == 0 || address > *obj_data_end)                *obj_data_end = address;        }    } while (object_address < *obj_data_base);     *obj_table_end = object_address - 1;     /* Skip any description for the last property */     if ((unsigned int) read_data_byte (obj_data_end))        while (((unsigned int) read_data_word (obj_data_end) & 0x8000) == 0)            ;     /* Skip any properties to calculate the end address of the last property */     while ((data = read_data_byte (obj_data_end)) != 0) {        if ((unsigned int) header.version < V4)            data_count = ((data & property_size_mask) >> 5) + 1;        else if (data & 0x80)            data_count = (unsigned int) read_data_byte (obj_data_end) & property_size_mask;        else if (data & 0x40)            data_count = 2;        else            data_count = 1;        *obj_data_end += data_count;    }     (*obj_data_end)--; }/* configure_object_tables */ /* * show_objects * * List all objects and property data. */ #ifdef __STDC__void show_objects (int symbolic)#elsevoid show_objects (symbolic)int symbolic;#endif{    unsigned long object_address, address;    unsigned long obj_table_base, obj_table_end, obj_data_base, obj_data_end;    unsigned int obj_count, data, pobj, nobj, cobj;    int i, j, k, list;    unsigned short inform_version;    unsigned long class_numbers_base, class_numbers_end;    unsigned long property_names_base, property_names_end;    unsigned long attr_names_base, attr_names_end;     /* Get objects configuration */     configure_object_tables (&obj_count, &obj_table_base, &obj_table_end,                             &obj_data_base, &obj_data_end);     if (symbolic) {    	configure_inform_tables(obj_data_end, &inform_version, &class_numbers_base, &class_numbers_end,    				    &property_names_base, &property_names_end, &attr_names_base, &attr_names_end);    }    else {	attr_names_base = property_names_base = class_numbers_base = 0;    }     tx_printf ("\n    **** Objects ****\n\n");    tx_printf ("  Object count = %d\n", (int) obj_count);     /* Iterate through each object */     for (i = 1; (unsigned int) i <= obj_count; i++) {        tx_printf ("\n");         /* Get address of object */         object_address = (unsigned long) get_object_address ((unsigned int) i);         /* Display attributes */         tx_printf ("%3d. Attributes: ", (int) i);        list = 0;        for (j = 0; j < (((unsigned int) header.version < V4) ? 4 : 6); j++) {            data = (unsigned int) read_data_byte (&object_address);            for (k = 7; k >= 0; k--) {                if ((data >> k) & 1) {					tx_printf ("%s", (list++) ? ", " : "");					if (print_attribute_name(attr_names_base, (int) ((j * 8) + (7 - k))))	                    tx_printf ("(%d)", (int) ((j * 8) + (7 - k)));					else	                    tx_printf ("%d", (int) ((j * 8) + (7 - k)));				}            }        }        if (list == 0)            tx_printf ("None");        tx_printf ("\n");         /* Get object linkage information */         if ((unsigned int) header.version < V4) {            pobj = (unsigned int) read_data_byte (&object_address);            nobj = (unsigned int) read_data_byte (&object_address);            cobj = (unsigned int) read_data_byte (&object_address);        } else {            pobj = (unsigned int) read_data_word (&object_address);            nobj = (unsigned int) read_data_word (&object_address);            cobj = (unsigned int) read_data_word (&object_address);        }        address = read_data_word (&object_address);        tx_printf ("     Parent object: %3d  ", (int) pobj);	tx_printf ("Sibling object: %3d  ", (int) nobj);	tx_printf ("Child object: %3d\n", (int) cobj);        tx_printf ("     Property address: %04lx\n", (unsigned long) address);        tx_printf ("         Description: \"");         /* If object has a description then display it */         if ((unsigned int) read_data_byte (&address))            (void) decode_text (&address);        tx_printf ("\"\n");         /* Print property list */         tx_printf ("          Properties:\n");	print_property_list (&address, property_names_base);    } }/* show_objects */ /* * get_object_address * * Given an object number calculate the data file address of the object data. */ #ifdef __STDC__static unsigned int get_object_address (unsigned int obj)#elsestatic unsigned int get_object_address (obj)unsigned int obj;#endif{    unsigned int offset;     /* Address calculation is object table base + size of default properties area +       object number-1 * object size */     offset = (unsigned int) header.objects;    if ((unsigned int) header.version <= V3)        offset += ((P3_MAX_PROPERTIES - 1) * 2) + ((obj - 1) * O3_SIZE);    else        offset += ((P4_MAX_PROPERTIES - 1) * 2) + ((obj - 1) * O4_SIZE);     return (offset); }/* get_object_address */ /* * print_property_list * * Display the data associated with each object property. */ #ifdef __STDC__static void print_property_list (unsigned long *address, unsigned long property_names_base)#elsestatic void print_property_list (address, property_names_base)unsigned long *address;unsigned long property_names_base;#endif{    int data, count;     /* Scan down the property address displaying each property */     for (data = read_data_byte (address); data; data = read_data_byte (address)) {	tx_printf ("            ");	if (print_property_name(property_names_base, (int) (data & property_mask)))		tx_printf ("\n              ");	else		tx_printf ("  ");	tx_printf ("[%2d] ", (int) (data & property_mask));	if ((unsigned int) header.version <= V3)	    count = ((data & property_size_mask) >> 5) + 1;	else if (data & 0x80)	    count = (unsigned int) read_data_byte (address) & property_size_mask;	else if (data & 0x40)	    count = 2;	else	    count = 1;        while (count--)            tx_printf ("%02x ", (unsigned int) read_data_byte (address));        tx_printf ("\n");    } }/* print_property_list */ /* * show_tree * * Use the object linkage information to display a hierarchical list of * objects. */ #ifdef __STDC__void show_tree (void)#elsevoid show_tree ()#endif{    unsigned long object_address;    unsigned long obj_table_base, obj_table_end, obj_data_base, obj_data_end;    unsigned int i, obj_count, parent;     /* Get objects configuration */     configure_object_tables (&obj_count, &obj_table_base, &obj_table_end,                             &obj_data_base, &obj_data_end);     tx_printf ("\n    **** Object tree ****\n\n");     /* Iterate through each object */     for (i = 1; i <= obj_count; i++) {         /* Get object address */         object_address = (unsigned long) get_object_address ((unsigned int) i);         /* Get parent for this object */         if ((unsigned int) header.version <= V3) {            object_address += O3_PARENT;            parent = read_data_byte (&object_address);        } else {            object_address += O4_PARENT;            parent = read_data_word (&object_address);        }         /*         * If object has no parent then it is a root object so display the tree         * from the object.         */         if (parent == 0)            print_object ((int) i, 0);    } }/* show_tree */ /* * print_object * * Print an object description and its children for a point in the object tree. */ #ifdef __STDC__static void print_object (int obj, int depth)#elsestatic void print_object (obj, depth)int obj;int depth;#endif{    unsigned long object_address, address;    int child, i;     /* Continue until the next object number is NULL */     while (obj) {         /* Display object depth and description */         for (i = 0; i < depth; i++)            tx_printf (" . ");        tx_printf ("[%3d] ", (int) obj);        print_object_desc (obj);        tx_printf ("\n");         /* Get object address */         object_address = (unsigned long) get_object_address ((unsigned int) obj);         /* Get any child object and the next object at this level */         if ((unsigned int) header.version <= V3) {            address = object_address + O3_CHILD;            child = read_data_byte (&address);            address = object_address + O3_NEXT;            obj = read_data_byte (&address);        } else {            address = object_address + O4_CHILD;            child = read_data_word (&address);            address = object_address + O4_NEXT;            obj = read_data_word (&address);        }         /* If this object has a child then print its tree */         if (child)            print_object (child, depth + 1);    } }/* print_object */ /* * print_object_description * * Display the description of an object. */

Lines 1–500 of 536.