예제 #1
0
        }/* z_print_num */

        /*
         * print_object
         *
         * Print an object description.
         *
         */

        internal static void print_object(zword object_var)
        {
            zword addr = CObject.object_name(object_var);
            zword code = 0x94a5;
            zbyte length;

            FastMem.LOW_BYTE(addr, out length);
            addr++;

            if (length != 0)
            {
                FastMem.LOW_WORD(addr, out code);
            }

            if (code == 0x94a5)         /* encoded text 0x94a5 == empty string */

            {
                print_string("object#");        /* supply a generic name */
                print_num(object_var);          /* for anonymous objects */
            }
            else
            {
                decode_text(string_type.LOW_STRING, addr);
            }
        }/* print_object */
예제 #2
0
        }/* z_get_prop_addr */

        /*
         * z_get_prop_len, store the length of an object property.
         *
         *  Process.zargs[0] = address of property to be examined
         *
         */

        internal static void z_get_prop_len()
        {
            zword addr;
            zbyte value;

            /* Back up the property pointer to the property id */

            addr = (zword)(Process.zargs[0] - 1);
            FastMem.LOW_BYTE(addr, out value);

            /* Calculate length of property */

            if (main.h_version <= ZMachine.V3)
            {
                value = (zbyte)((value >> 5) + 1);
            }
            else if (!((value & 0x80) > 0))
            {
                value = (zbyte)((value >> 6) + 1);
            }
            else
            {
                value &= 0x3f;

                if (value == 0)
                {
                    value = 64;                 /* demanded by Spec 1.0 */
                }
            }

            /* Store length of property */

            Process.store(value);
        }/* z_get_prop_len */
예제 #3
0
        }/* lookup_text */

        /*
         * tokenise_text
         *
         * Translate a single word to a token and append it to the token
         * buffer. Every token consists of the address of the dictionary
         * entry, the length of the word and the offset of the word from
         * the start of the text buffer. Unknown words cause empty slots
         * if the flag is set (such that the text can be scanned several
         * times with different dictionaries); otherwise they are zero.
         *
         */

        static void tokenise_text(zword text, zword length, zword from, zword parse, zword dct, bool flag)
        {
            zword addr;
            zbyte token_max, token_count;

            FastMem.LOW_BYTE(parse, out token_max);
            parse++;
            FastMem.LOW_BYTE(parse, out token_count);

            if (token_count < token_max)        /* sufficient space left for token? */

            {
                FastMem.storeb(parse++, (zbyte)(token_count + 1));

                load_string((zword)(text + from), length);

                addr = lookup_text(0x05, dct);

                if (addr != 0 || !flag)
                {
                    parse += (zword)(4 * token_count); // Will parse get updated properly?

                    FastMem.storew((zword)(parse + 0), addr);
                    FastMem.storeb((zword)(parse + 2), (zbyte)length);
                    FastMem.storeb((zword)(parse + 3), (zbyte)from);
                }
            }
        }/* tokenise_text */
예제 #4
0
        }/* z_print_char */

        /*
         * z_print_form, print a formatted table.
         *
         *	zargs[0] = address of formatted table to be printed
         *
         */

        internal static void z_print_form()
        {
            zword count;
            zword addr = Process.zargs[0];

            bool first = true;

            for (;;)
            {
                FastMem.LOW_WORD(addr, out count);
                addr += 2;

                if (count == 0)
                {
                    break;
                }

                if (!first)
                {
                    Buffer.new_line();
                }

                while (count-- > 0)
                {
                    zbyte c;

                    FastMem.LOW_BYTE(addr, out c);
                    addr++;

                    Buffer.print_char(translate_from_zscii(c));
                }

                first = false;
            }
        }/* z_print_form */
예제 #5
0
        }/* find_resolution */

        /*
         * load_string
         *
         * Copy a ZSCII string from the memory to the global "decoded" string.
         *
         */

        internal static void load_string(zword addr, zword length)
        {
            int i = 0;

            if (resolution == 0)
            {
                find_resolution();
            }

            while (i < 3 * resolution)
            {
                if (i < length)
                {
                    zbyte c;

                    FastMem.LOW_BYTE(addr, out c);
                    addr++;

                    decoded[i++] = Text.translate_from_zscii(c);
                }
                else
                {
                    decoded[i++] = 0;
                }
            }
        }/* load_string */
예제 #6
0
        }/* translate_to_zscii */

        /*
         * alphabet
         *
         * Return a character from one of the three character sets.
         *
         */

        static zword alphabet(int set, int index)
        {
            if (main.h_version > ZMachine.V1 && set == 2 && index == 1)
            {
                return(0x0D);           /* always newline */
            }
            if (main.h_alphabet != 0)   /* game uses its own alphabet */

            {
                zbyte c;

                zword addr = (zword)(main.h_alphabet + 26 * set + index);
                FastMem.LOW_BYTE(addr, out c);

                return(translate_from_zscii(c));
            }
            else                        /* game uses default alphabet */

            if (set == 0)
            {
                return((zword)('a' + index));
            }
            else if (set == 1)
            {
                return((zword)('A' + index));
            }
            else if (main.h_version == ZMachine.V1)
            {
                return(" 0123456789.,!?_#'\"/\\<-:()"[index]);
            }
            else
            {
                return(" ^0123456789.,!?_#'\"/\\-:()"[index]);
            }
        }/* alphabet */
예제 #7
0
        }/* first_property */

        /*
         * next_property
         *
         * Calculate the address of the next property in a property list.
         *
         */

        static zword next_property(zword prop_addr)
        {
            zbyte value;

            /* Load the current property id */

            FastMem.LOW_BYTE(prop_addr, out value);
            prop_addr++;

            /* Calculate the length of this property */

            if (main.h_version <= ZMachine.V3)
            {
                value >>= 5;
            }
            else if (!((value & 0x80) > 0))
            {
                value >>= 6;
            }
            else
            {
                FastMem.LOW_BYTE(prop_addr, out value);
                value &= 0x3f;

                if (value == 0)
                {
                    value = 64;                 /* demanded by Spec 1.0 */
                }
            }

            /* Add property length to current property pointer */

            return((zword)(prop_addr + value + 1));
        }/* next_property */
예제 #8
0
        internal static void z_make_menu()
        {
            /* This opcode was only used for the Macintosh version of Journey.
             * It controls menus with numbers greater than 2 (menus 0, 1 and 2
             * are system menus). */

            if (Process.zargs[0] < 3)
            {
                Process.branch(false);
                return;
            }

            if (Process.zargs[1] != 0)
            {
                zword items;
                int   i;

                FastMem.LOW_WORD(Process.zargs[1], out items);

                for (i = 0; i < items; i++)
                {
                    zword item;
                    zbyte length;
                    zbyte c;
                    int   j;

                    FastMem.LOW_WORD(Process.zargs[1] + 2 + (2 * i), out item);
                    FastMem.LOW_BYTE(item, out length);

                    if (length > 31)
                    {
                        length = 31;
                    }
                    menu[length] = 0;

                    for (j = 0; j < length; j++)
                    {
                        FastMem.LOW_BYTE(item + j + 1, out c);
                        menu[j] = Text.translate_from_zscii(c);
                    }

                    if (i == 0)
                    {
                        os_.menu(ZMachine.MENU_NEW, Process.zargs[0], menu);
                    }
                    else
                    {
                        os_.menu(ZMachine.MENU_ADD, Process.zargs[0], menu);
                    }
                }
            }
            else
            {
                os_.menu(ZMachine.MENU_REMOVE, Process.zargs[0], new zword[0]);
            }

            Process.branch(true);
        }/* z_make_menu */
예제 #9
0
        /*
         * translate_from_zscii
         *
         * Map a ZSCII character into Unicode.
         *
         */

        internal static zword translate_from_zscii(zbyte c)
        {
            if (c == 0xfc)
            {
                return(CharCodes.ZC_MENU_CLICK);
            }
            if (c == 0xfd)
            {
                return(CharCodes.ZC_DOUBLE_CLICK);
            }
            if (c == 0xfe)
            {
                return(CharCodes.ZC_SINGLE_CLICK);
            }

            if (c >= 0x9b && main.story_id != Story.BEYOND_ZORK)
            {
                if (main.hx_unicode_table != 0)         /* game has its own Unicode table */

                {
                    zbyte N;

                    FastMem.LOW_BYTE(main.hx_unicode_table, out N);

                    if (c - 0x9b < N)
                    {
                        zword addr = (zword)(main.hx_unicode_table + 1 + 2 * (c - 0x9b));
                        zword unicode;

                        FastMem.LOW_WORD(addr, out unicode);

                        if (unicode < 0x20)
                        {
                            return('?');
                        }

                        return(unicode);
                    }
                    else
                    {
                        return('?');
                    }
                }
                else                            /* game uses standard set */

                if (c <= 0xdf)
                {
                    return(zscii_to_latin1[c - 0x9b]);
                }
                else
                {
                    return('?');
                }
            }

            return((zword)c);
        }/* translate_from_zscii */
예제 #10
0
        }/* z_copy_table */

        /*
         * z_loadb, store a value from a table of bytes.
         *
         *	zargs[0] = address of table
         *	zargs[1] = index of table entry to store
         *
         */

        internal static void z_loadb()
        {
            zword addr = (zword)(Process.zargs[0] + Process.zargs[1]);
            zbyte value;

            FastMem.LOW_BYTE(addr, out value);

            Process.store(value);
        }/* z_loadb */
예제 #11
0
        }/* z_get_prop */

        /*
         * z_get_prop_addr, store the address of an object property.
         *
         *	Process.zargs[0] = object
         *	Process.zargs[1] = number of property to be examined
         *
         */

        internal static void z_get_prop_addr()
        {
            zword prop_addr;
            zbyte value;
            zbyte mask;

            if (Process.zargs[0] == 0)
            {
                Err.runtime_error(ErrorCodes.ERR_GET_PROP_ADDR_0);
                Process.store(0);
                return;
            }

            if (main.story_id == Story.BEYOND_ZORK)
            {
                if (Process.zargs[0] > MAX_OBJECT)
                {
                    Process.store(0); return;
                }
            }

            /* Property id is in bottom five (six) bits */

            mask = (zbyte)((main.h_version <= ZMachine.V3) ? 0x1f : 0x3f);

            /* Load address of first property */

            prop_addr = first_property(Process.zargs[0]);

            /* Scan down the property list */

            for (; ;)
            {
                FastMem.LOW_BYTE(prop_addr, out value);
                if ((value & mask) <= Process.zargs[1])
                {
                    break;
                }
                prop_addr = next_property(prop_addr);
            }

            /* Calculate the property address or return zero */

            if ((value & mask) == Process.zargs[1])
            {
                if (main.h_version >= ZMachine.V4 && (value & 0x80) > 0)
                {
                    prop_addr++;
                }
                Process.store((zword)(prop_addr + 1));
            }
            else
            {
                Process.store(0);
            }
        }/* z_get_prop_addr */
예제 #12
0
        }/* z_insert_obj */

        /*
         * z_put_prop, set the value of an object property.
         *
         *	Process.zargs[0] = object
         *	Process.zargs[1] = number of property to set
         *	Process.zargs[2] = value to set property to
         *
         */

        internal static void z_put_prop()
        {
            zword prop_addr;
            zbyte value;
            zbyte mask;

            if (Process.zargs[0] == 0)
            {
                Err.runtime_error(ErrorCodes.ERR_PUT_PROP_0);
                return;
            }

            /* Property id is in bottom five or six bits */

            mask = (zbyte)((main.h_version <= ZMachine.V3) ? 0x1f : 0x3f);

            /* Load address of first property */

            prop_addr = first_property(Process.zargs[0]);

            /* Scan down the property list */

            for (; ;)
            {
                FastMem.LOW_BYTE(prop_addr, out value);
                if ((value & mask) <= Process.zargs[1])
                {
                    break;
                }
                prop_addr = next_property(prop_addr);
            }

            /* Exit if the property does not exist */

            if ((value & mask) != Process.zargs[1])
            {
                Err.runtime_error(ErrorCodes.ERR_NO_PROP);
            }

            /* Store the new property value (byte or word sized) */

            prop_addr++;

            if ((main.h_version <= ZMachine.V3 && !((value & 0xe0) > 0)) || (main.h_version >= ZMachine.V4 && !((value & 0xc0) > 0)))
            {
                zbyte v = (zbyte)Process.zargs[2];
                FastMem.SET_BYTE(prop_addr, v);
            }
            else
            {
                zword v = Process.zargs[2];
                FastMem.SET_WORD(prop_addr, v);
            }
        }/* z_put_prop */
예제 #13
0
        }/* z_jin */

        /*
         * z_get_child, store the child of an object.
         *
         *	Process.zargs[0] = object
         *
         */

        internal static void z_get_child()
        {
            zword obj_addr;

            /* If we are monitoring object locating display a short note */

            if (main.option_object_locating == true)
            {
                Stream.stream_mssg_on();
                Text.print_string("@get_child ");
                Text.print_object(Process.zargs[0]);
                Stream.stream_mssg_off();
            }

            if (Process.zargs[0] == 0)
            {
                Err.runtime_error(ErrorCodes.ERR_GET_CHILD_0);
                Process.store(0);
                Process.branch(false);
                return;
            }

            obj_addr = object_address(Process.zargs[0]);

            if (main.h_version <= ZMachine.V3)
            {
                zbyte child;

                /* Get child id from object */

                obj_addr += O1_CHILD;
                FastMem.LOW_BYTE(obj_addr, out child);

                /* Store child id and branch */

                Process.store(child);
                Process.branch(child > 0);
            }
            else
            {
                zword child;

                /* Get child id from object */

                obj_addr += O4_CHILD;
                FastMem.LOW_WORD(obj_addr, out child);

                /* Store child id and branch */

                Process.store(child);
                Process.branch(child > 0);
            }
        }/* z_get_child */
예제 #14
0
        }/* z_remove_obj */

        /*
         * z_set_attr, set an object attribute.
         *
         *	Process.zargs[0] = object
         *	Process.zargs[1] = number of attribute to set
         *
         */

        internal static void z_set_attr()
        {
            zword obj_addr;
            zbyte value;

            if (main.story_id == Story.SHERLOCK)
            {
                if (Process.zargs[1] == 48)
                {
                    return;
                }
            }

            if (Process.zargs[1] > ((main.h_version <= ZMachine.V3) ? 31 : 47))
            {
                Err.runtime_error(ErrorCodes.ERR_ILL_ATTR);
            }

            /* If we are monitoring attribute assignment display a short note */

            if (main.option_attribute_assignment == true)
            {
                Stream.stream_mssg_on();
                Text.print_string("@set_attr ");
                Text.print_object(Process.zargs[0]);
                Text.print_string(" ");
                Text.print_num(Process.zargs[1]);
                Stream.stream_mssg_off();
            }

            if (Process.zargs[0] == 0)
            {
                Err.runtime_error(ErrorCodes.ERR_SET_ATTR_0);
                return;
            }

            /* Get attribute address */

            obj_addr = (zword)(object_address(Process.zargs[0]) + Process.zargs[1] / 8);

            /* Load attribute byte */

            FastMem.LOW_BYTE(obj_addr, out value);

            /* Set attribute bit */

            value |= (zbyte)(0x80 >> (Process.zargs[1] & 7));

            /* Store attribute byte */

            FastMem.SET_BYTE(obj_addr, value);
        }/* z_set_attr */
예제 #15
0
        }/* z_clear_attr */

        /*
         * z_jin, branch if the first object is inside the second.
         *
         *	Process.zargs[0] = first object
         *	Process.zargs[1] = second object
         *
         */

        internal static void z_jin()
        {
            zword obj_addr;

            /* If we are monitoring object locating display a short note */

            if (main.option_object_locating == true)
            {
                Stream.stream_mssg_on();
                Text.print_string("@jin ");
                Text.print_object(Process.zargs[0]);
                Text.print_string(" ");
                Text.print_object(Process.zargs[1]);
                Stream.stream_mssg_off();
            }

            if (Process.zargs[0] == 0)
            {
                Err.runtime_error(ErrorCodes.ERR_JIN_0);
                Process.branch(0 == Process.zargs[1]);
                return;
            }

            obj_addr = object_address(Process.zargs[0]);

            if (main.h_version <= ZMachine.V3)
            {
                zbyte parent;

                /* Get parent id from object */

                obj_addr += O1_PARENT;
                FastMem.LOW_BYTE(obj_addr, out parent);

                /* Branch if the parent is obj2 */

                Process.branch(parent == Process.zargs[1]);
            }
            else
            {
                zword parent;

                /* Get parent id from object */

                obj_addr += O4_PARENT;
                FastMem.LOW_WORD(obj_addr, out parent);

                /* Branch if the parent is obj2 */

                Process.branch(parent == Process.zargs[1]);
            }
        }/* z_jin */
예제 #16
0
        }/* z_loadw */

        /*
         * z_scan_table, find and store the address of a target within a table.
         *
         *	zargs[0] = target value to be searched for
         *	zargs[1] = address of table
         *	zargs[2] = number of table entries to check value against
         *	zargs[3] = type of table (optional, defaults to 0x82)
         *
         * Note: The table is a word array if bit 7 of zargs[3] is set; otherwise
         *       it's a byte array. The lower bits hold the address step.
         *
         */

        internal static void z_scan_table()
        {
            zword addr = Process.zargs[1];
            int   i;

            /* Supply default arguments */

            if (Process.zargc < 4)
            {
                Process.zargs[3] = 0x82;
            }

            /* Scan byte or word array */

            for (i = 0; i < Process.zargs[2]; i++)
            {
                if ((Process.zargs[3] & 0x80) > 0)      /* scan word array */

                {
                    zword wvalue;

                    FastMem.LOW_WORD(addr, out wvalue);

                    if (wvalue == Process.zargs[0])
                    {
                        goto finished;
                    }
                }
                else            /* scan byte array */

                {
                    zbyte bvalue;

                    FastMem.LOW_BYTE(addr, out bvalue);

                    if (bvalue == Process.zargs[0])
                    {
                        goto finished;
                    }
                }

                addr += (zword)(Process.zargs[3] & 0x7f);
            }

            addr = 0;

finished:

            Process.store(addr);
            Process.branch(addr > 0);
        }/* z_scan_table */
예제 #17
0
        }/* object_name */

        /*
         * first_property
         *
         * Calculate the start address of the property list associated with
         * an object.
         *
         */

        static zword first_property(zword obj)
        {
            zword prop_addr;
            zbyte size;

            /* Fetch address of object name */

            prop_addr = object_name(obj);

            /* Get length of object name */

            FastMem.LOW_BYTE(prop_addr, out size);

            /* Add name length to pointer */

            return((zword)(prop_addr + 1 + 2 * size));
        }/* first_property */
예제 #18
0
        }/* translate_from_zscii */

        /*
         * unicode_to_zscii
         *
         * Convert a Unicode character to ZSCII, returning 0 on failure.
         *
         */

        internal static zbyte unicode_to_zscii(zword c)
        {
            int i;

            if (c >= CharCodes.ZC_LATIN1_MIN)
            {
                if (main.hx_unicode_table != 0)         /* game has its own Unicode table */

                {
                    zbyte N;

                    FastMem.LOW_BYTE(main.hx_unicode_table, out N);

                    for (i = 0x9b; i < 0x9b + N; i++)
                    {
                        zword addr = (zword)(main.hx_unicode_table + 1 + 2 * (i - 0x9b));
                        zword unicode;

                        FastMem.LOW_WORD(addr, out unicode);

                        if (c == unicode)
                        {
                            return((zbyte)i);
                        }
                    }

                    return(0);
                }
                else                            /* game uses standard set */

                {
                    for (i = 0x9b; i <= 0xdf; i++)
                    {
                        if (c == zscii_to_latin1[i - 0x9b])
                        {
                            return((zbyte)i);
                        }
                    }

                    return(0);
                }
            }

            return((zbyte)c);
        }/* unicode_to_zscii */
예제 #19
0
        }/* z_get_child */

        /*
         * z_get_next_prop, store the number of the first or next property.
         *
         *	Process.zargs[0] = object
         *	Process.zargs[1] = address of current property (0 gets the first property)
         *
         */

        internal static void z_get_next_prop()
        {
            zword prop_addr;
            zbyte value;
            zbyte mask;

            if (Process.zargs[0] == 0)
            {
                Err.runtime_error(ErrorCodes.ERR_GET_NEXT_PROP_0);
                Process.store(0);
                return;
            }

            /* Property id is in bottom five (six) bits */

            mask = (zbyte)((main.h_version <= ZMachine.V3) ? 0x1f : 0x3f);

            /* Load address of first property */

            prop_addr = first_property(Process.zargs[0]);

            if (Process.zargs[1] != 0)
            {
                /* Scan down the property list */

                do
                {
                    FastMem.LOW_BYTE(prop_addr, out value);
                    prop_addr = next_property(prop_addr);
                } while ((value & mask) > Process.zargs[1]);

                /* Exit if the property does not exist */

                if ((value & mask) != Process.zargs[1])
                {
                    Err.runtime_error(ErrorCodes.ERR_NO_PROP);
                }
            }

            /* Return the property id */

            FastMem.LOW_BYTE(prop_addr, out value);
            Process.store((zword)(value & mask));
        }/* z_get_next_prop */
예제 #20
0
        }/* z_get_prop_len */

        /*
         * z_get_sibling, store the sibling of an object.
         *
         *	Process.zargs[0] = object
         *
         */

        internal static void z_get_sibling()
        {
            zword obj_addr;

            if (Process.zargs[0] == 0)
            {
                Err.runtime_error(ErrorCodes.ERR_GET_SIBLING_0);
                Process.store(0);
                Process.branch(false);
                return;
            }

            obj_addr = object_address(Process.zargs[0]);

            if (main.h_version <= ZMachine.V3)
            {
                zbyte sibling;

                /* Get sibling id from object */

                obj_addr += O1_SIBLING;
                FastMem.LOW_BYTE(obj_addr, out sibling);

                /* Store sibling and branch */

                Process.store(sibling);
                Process.branch(sibling > 0); // TODO I'm not sure about this logic Process.branch (sibling);
                // I think it means if the sibling isn't zero, jump..
            }
            else
            {
                zword sibling;

                /* Get sibling id from object */

                obj_addr += O4_SIBLING;
                FastMem.LOW_WORD(obj_addr, out sibling);

                /* Store sibling and branch */

                Process.store(sibling);
                Process.branch(sibling > 0);
            }
        }/* z_get_sibling */
예제 #21
0
        }/* z_restart */

        /*
         * get_default_name
         *
         * Read a default file name from the memory of the Z-machine and
         * copy it to a string.
         *
         */

        internal static string get_default_name(zword addr)
        {
            if (addr != 0)
            {
                var sb = new System.Text.StringBuilder();

                zbyte len;
                int   i;

                FastMem.LOW_BYTE(addr, out len);
                addr++;

                for (i = 0; i < len; i++)
                {
                    zbyte c;

                    FastMem.LOW_BYTE(addr, out c);
                    addr++;

                    if (c >= 'A' && c <= 'Z')
                    {
                        c += 'a' - 'A';
                    }

                    // default_name[i] = c;
                    sb.Append((char)c);
                }

                // default_name[i] = 0;

                if (sb.ToString().IndexOf(".") == -1)
                {
                    sb.Append(".AUX");
                    return(sb.ToString());
                }
                else
                {
                    return(auxilary_name);
                }
            }
            return(null);
        }/* get_default_name */
예제 #22
0
        }/* alphabet */

        /*
         * find_resolution
         *
         * Find the number of bytes used for dictionary resolution.
         *
         */

        internal static void find_resolution()
        {
            zword dct = main.h_dictionary;
            zbyte sep_count;
            zbyte entry_len;

            FastMem.LOW_BYTE(dct, out sep_count);
            dct += (zword)(1 + sep_count);  /* skip word separators */
            FastMem.LOW_BYTE(dct, out entry_len);

            resolution = (main.h_version <= ZMachine.V3) ? 2 : 3;

            if (2 * resolution > entry_len)
            {
                Err.runtime_error(ErrorCodes.ERR_DICT_LEN);
            }

            decoded = new zword[3 * resolution + 1];
            encoded = new zword[resolution];
        }/* find_resolution */
예제 #23
0
        }/* z_set_attr */

        /*
         * z_test_attr, branch if an object attribute is set.
         *
         *	Process.zargs[0] = object
         *	Process.zargs[1] = number of attribute to test
         *
         */

        internal static void z_test_attr()
        {
            zword obj_addr;
            zbyte value;

            if (Process.zargs[1] > ((main.h_version <= ZMachine.V3) ? 31 : 47))
            {
                Err.runtime_error(ErrorCodes.ERR_ILL_ATTR);
            }

            /* If we are monitoring attribute testing display a short note */

            if (main.option_attribute_testing == true)
            {
                Stream.stream_mssg_on();
                Text.print_string("@test_attr ");
                Text.print_object(Process.zargs[0]);
                Text.print_string(" ");
                Text.print_num(Process.zargs[1]);
                Stream.stream_mssg_off();
            }

            if (Process.zargs[0] == 0)
            {
                Err.runtime_error(ErrorCodes.ERR_TEST_ATTR_0);
                Process.branch(false);
                return;
            }

            /* Get attribute address */

            obj_addr = (zword)(object_address(Process.zargs[0]) + Process.zargs[1] / 8);

            /* Load attribute byte */

            FastMem.LOW_BYTE(obj_addr, out value);

            /* Test attribute */

            Process.branch((value & (0x80 >> (Process.zargs[1] & 7))) > 0);
        }/* z_test_attr */
예제 #24
0
        /*
         * z_copy_table, copy a table or fill it with zeroes.
         *
         *	zargs[0] = address of table
         *  zargs[1] = destination address or 0 for fill
         *	zargs[2] = size of table
         *
         * Note: Copying is safe even when source and destination overlap; but
         *       if zargs[1] is negative the table _must_ be copied forwards.
         *
         */

        internal static void z_copy_table()
        {
            zword addr;
            zword size = Process.zargs[2];
            zbyte value;
            int   i;

            if (Process.zargs[1] == 0)                                  /* zero table */

            {
                for (i = 0; i < size; i++)
                {
                    FastMem.storeb((zword)(Process.zargs[0] + i), 0);
                }
            }

            else if ((short)size < 0 || Process.zargs[0] > Process.zargs[1])    /* copy forwards */

            {
                for (i = 0; i < (((short)size < 0) ? -(short)size : size); i++)
                {
                    addr = (zword)(Process.zargs[0] + i);
                    FastMem.LOW_BYTE(addr, out value);
                    FastMem.storeb((zword)(Process.zargs[1] + i), value);
                }
            }

            else                                                /* copy backwards */

            {
                for (i = size - 1; i >= 0; i--)
                {
                    addr = (zword)(Process.zargs[0] + i);
                    FastMem.LOW_BYTE(addr, out value);
                    FastMem.storeb((zword)(Process.zargs[1] + i), value);
                }
            }
        }/* z_copy_table */
예제 #25
0
        //zword unicode_tolower (zword);

        /*
         * is_terminator
         *
         * Check if the given key is an input terminator.
         *
         */

        internal static bool is_terminator(zword key)
        {
            if (key == CharCodes.ZC_TIME_OUT)
            {
                return(true);
            }
            if (key == CharCodes.ZC_RETURN)
            {
                return(true);
            }
            if (key >= CharCodes.ZC_HKEY_MIN && key <= CharCodes.ZC_HKEY_MAX)
            {
                return(true);
            }

            if (main.h_terminating_keys != 0)
            {
                if (key >= CharCodes.ZC_ARROW_MIN && key <= CharCodes.ZC_MENU_CLICK)
                {
                    zword addr = main.h_terminating_keys;
                    zbyte c;

                    do
                    {
                        FastMem.LOW_BYTE(addr, out c);
                        if (c == 255 || key == Text.translate_from_zscii(c))
                        {
                            return(true);
                        }
                        addr++;
                    } while (c != 0);
                }
            }

            return(false);
        }/* is_terminator */
예제 #26
0
        }/* next_property */

        /*
         * unlink_object
         *
         * Unlink an object from its parent and siblings.
         *
         */

        static void unlink_object(zword object_var)
        {
            zword obj_addr;
            zword parent_addr;
            zword sibling_addr;

            if (object_var == 0)
            {
                Err.runtime_error(ErrorCodes.ERR_REMOVE_OBJECT_0);
                return;
            }

            obj_addr = object_address(object_var);

            if (main.h_version <= ZMachine.V3)
            {
                zbyte parent;
                zbyte younger_sibling;
                zbyte older_sibling;
                zbyte zero = 0;

                /* Get parent of object, and return if no parent */

                obj_addr += O1_PARENT;
                FastMem.LOW_BYTE(obj_addr, out parent);
                if (parent == 0)
                {
                    return;
                }

                /* Get (older) sibling of object and set both parent and sibling
                 * pointers to 0 */

                FastMem.SET_BYTE(obj_addr, zero);
                obj_addr += (zword)(O1_SIBLING - O1_PARENT);
                FastMem.LOW_BYTE(obj_addr, out older_sibling);
                FastMem.SET_BYTE(obj_addr, zero);

                /* Get first child of parent (the youngest sibling of the object) */

                parent_addr = (zword)(object_address(parent) + O1_CHILD);
                FastMem.LOW_BYTE(parent_addr, out younger_sibling);

                /* Remove object from the list of siblings */

                if (younger_sibling == object_var)
                {
                    FastMem.SET_BYTE(parent_addr, older_sibling);
                }
                else
                {
                    do
                    {
                        sibling_addr = (zword)(object_address(younger_sibling) + O1_SIBLING);
                        FastMem.LOW_BYTE(sibling_addr, out younger_sibling);
                    } while (younger_sibling != object_var);
                    FastMem.SET_BYTE(sibling_addr, older_sibling);
                }
            }
            else
            {
                zword parent;
                zword younger_sibling;
                zword older_sibling;
                zword zero = 0;

                /* Get parent of object, and return if no parent */

                obj_addr += O4_PARENT;
                FastMem.LOW_WORD(obj_addr, out parent);
                if (parent == 0)
                {
                    return;
                }

                /* Get (older) sibling of object and set both parent and sibling
                 * pointers to 0 */

                FastMem.SET_WORD(obj_addr, zero);
                obj_addr += (zword)(O4_SIBLING - O4_PARENT);
                FastMem.LOW_WORD(obj_addr, out older_sibling);
                FastMem.SET_WORD(obj_addr, zero);

                /* Get first child of parent (the youngest sibling of the object) */

                parent_addr = (zword)(object_address(parent) + O4_CHILD);
                FastMem.LOW_WORD(parent_addr, out younger_sibling);

                /* Remove object from the list of siblings */

                if (younger_sibling == object_var)
                {
                    FastMem.SET_WORD(parent_addr, older_sibling);
                }
                else
                {
                    do
                    {
                        sibling_addr = (zword)(object_address(younger_sibling) + O4_SIBLING);
                        FastMem.LOW_WORD(sibling_addr, out younger_sibling);
                    } while (younger_sibling != object_var);
                    FastMem.SET_WORD(sibling_addr, older_sibling);
                }
            }
        }/* unlink_object */
예제 #27
0
        }/* read_number */

        /*
         * z_read, read a line of input and (in V5+) store the terminating key.
         *
         *	zargs[0] = address of text buffer
         *	zargs[1] = address of token buffer
         *	zargs[2] = timeout in tenths of a second (optional)
         *	zargs[3] = packed address of routine to be called on timeout
         *
         */

        internal static void z_read()
        {
            zword[] buffer = new zword[General.INPUT_BUFFER_SIZE];
            zword   addr;
            zword   key;
            zbyte   max, size;
            zbyte   c;
            int     i;

            /* Supply default arguments */

            if (Process.zargc < 3)
            {
                Process.zargs[2] = 0;
            }

            /* Get maximum input size */

            addr = Process.zargs[0];

            FastMem.LOW_BYTE(addr, out max);

            if (main.h_version <= ZMachine.V4)
            {
                max--;
            }

            if (max >= General.INPUT_BUFFER_SIZE)
            {
                max = (zbyte)(General.INPUT_BUFFER_SIZE - 1);
            }

            /* Get initial input size */

            if (main.h_version >= ZMachine.V5)
            {
                addr++;
                FastMem.LOW_BYTE(addr, out size);
            }
            else
            {
                size = 0;
            }

            /* Copy initial input to local buffer */

            for (i = 0; i < size; i++)
            {
                addr++;
                FastMem.LOW_BYTE(addr, out c);
                buffer[i] = Text.translate_from_zscii(c);
            }

            buffer[i] = 0;

            /* Draw status line for V1 to V3 games */

            if (main.h_version <= ZMachine.V3)
            {
                Screen.z_show_status();
            }

            /* Read input from current input stream */

            key = Stream.stream_read_input(
                max, buffer,                    /* buffer and size */
                Process.zargs[2],               /* timeout value   */
                Process.zargs[3],               /* timeout routine */
                true,                           /* enable hot keys */
                main.h_version == ZMachine.V6); /* no script in V6 */

            if (key == CharCodes.ZC_BAD)
            {
                return;
            }

            /* Perform save_undo for V1 to V4 games */

            if (main.h_version <= ZMachine.V4)
            {
                FastMem.save_undo();
            }

            /* Copy local buffer back to dynamic memory */

            for (i = 0; buffer[i] != 0; i++)
            {
                if (key == CharCodes.ZC_RETURN)
                {
                    buffer[i] = Text.unicode_tolower(buffer[i]);
                }

                FastMem.storeb((zword)(Process.zargs[0] + ((main.h_version <= ZMachine.V4) ? 1 : 2) + i), Text.translate_to_zscii(buffer[i]));
            }

            /* Add null character (V1-V4) or write input length into 2nd byte */

            if (main.h_version <= ZMachine.V4)
            {
                FastMem.storeb((zword)(Process.zargs[0] + 1 + i), 0);
            }
            else
            {
                FastMem.storeb((zword)(Process.zargs[0] + 1), (byte)i);
            }

            /* Tokenise line if a token buffer is present */

            if (key == CharCodes.ZC_RETURN && Process.zargs[1] != 0)
            {
                Text.tokenise_line(Process.zargs[0], Process.zargs[1], 0, false);
            }

            /* Store key */

            if (main.h_version >= ZMachine.V5)
            {
                Process.store(Text.translate_to_zscii(key));
            }
        }/* z_read */
예제 #28
0
        }/* z_print_unicode */

        /*
         * lookup_text
         *
         * Scan a dictionary searching for the given word. The first argument
         * can be
         *
         * 0x00 - find the first word which is >= the given one
         * 0x05 - find the word which exactly matches the given one
         * 0x1f - find the last word which is <= the given one
         *
         * The return value is 0 if the search fails.
         *
         */

        internal static zword lookup_text(int padding, zword dct)
        {
            zword entry_addr;
            zword entry_count;
            zword entry;
            zword addr;
            zbyte entry_len;
            zbyte sep_count;
            int   entry_number;
            int   lower, upper;
            int   i;
            bool  sorted;

            if (resolution == 0)
            {
                find_resolution();
            }

            Text.encode_text(padding);

            FastMem.LOW_BYTE(dct, out sep_count);               /* skip word separators */
            dct += (zword)(1 + sep_count);
            FastMem.LOW_BYTE(dct, out entry_len);               /* get length of entries */
            dct += 1;
            FastMem.LOW_WORD(dct, out entry_count);             /* get number of entries */
            dct += 2;

            if ((short)entry_count < 0)         /* bad luck, entries aren't sorted */

            {
                entry_count = (zword)(-(short)entry_count);
                sorted      = false;
            }
            else
            {
                sorted = true;                  /* entries are sorted */
            }
            lower = 0;
            upper = entry_count - 1;

            while (lower <= upper)
            {
                if (sorted)                             /* binary search */
                {
                    entry_number = (lower + upper) / 2;
                }
                else                                    /* linear search */
                {
                    entry_number = lower;
                }

                entry_addr = (zword)(dct + entry_number * entry_len);

                /* Compare word to dictionary entry */

                addr = entry_addr;

                for (i = 0; i < resolution; i++)
                {
                    FastMem.LOW_WORD(addr, out entry);
                    if (encoded[i] != entry)
                    {
                        goto continuing;
                    }
                    addr += 2;
                }

                return(entry_addr);              /* exact match found, return now */

continuing:

                if (sorted)                             /* binary search */

                {
                    if (encoded[i] > entry)
                    {
                        lower = entry_number + 1;
                    }
                    else
                    {
                        upper = entry_number - 1;
                    }
                }

                else
                {
                    lower++;                            /* linear search */
                }
            }

            /* No exact match has been found */

            if (padding == 0x05)
            {
                return(0);
            }

            entry_number = (padding == 0x00) ? lower : upper;

            if (entry_number == -1 || entry_number == entry_count)
            {
                return(0);
            }

            return((zword)(dct + entry_number * entry_len));
        }/* lookup_text */
예제 #29
0
        }/* z_get_sibling */

        /*
         * z_insert_obj, make an object the first child of another object.
         *
         *	Process.zargs[0] = object to be moved
         *	Process.zargs[1] = destination object
         *
         */

        internal static void z_insert_obj()
        {
            zword obj1 = Process.zargs[0];
            zword obj2 = Process.zargs[1];
            zword obj1_addr;
            zword obj2_addr;

            /* If we are monitoring object movements display a short note */

            if (main.option_object_movement == true)
            {
                Stream.stream_mssg_on();
                Text.print_string("@move_obj ");
                Text.print_object(obj1);
                Text.print_string(" ");
                Text.print_object(obj2);
                Stream.stream_mssg_off();
            }

            if (obj1 == 0)
            {
                Err.runtime_error(ErrorCodes.ERR_MOVE_OBJECT_0);
                return;
            }

            if (obj2 == 0)
            {
                Err.runtime_error(ErrorCodes.ERR_MOVE_OBJECT_TO_0);
                return;
            }

            /* Get addresses of both objects */

            obj1_addr = object_address(obj1);
            obj2_addr = object_address(obj2);

            /* Remove object 1 from current parent */

            unlink_object(obj1);

            /* Make object 1 first child of object 2 */

            if (main.h_version <= ZMachine.V3)
            {
                zbyte child;

                obj1_addr += O1_PARENT;
                FastMem.SET_BYTE(obj1_addr, (zbyte)obj2);
                obj2_addr += O1_CHILD;
                FastMem.LOW_BYTE(obj2_addr, out child);
                FastMem.SET_BYTE(obj2_addr, (zbyte)obj1);
                obj1_addr += (zword)(O1_SIBLING - O1_PARENT);
                FastMem.SET_BYTE(obj1_addr, child);
            }
            else
            {
                zword child;

                obj1_addr += O4_PARENT;
                FastMem.SET_WORD(obj1_addr, obj2);
                obj2_addr += O4_CHILD;
                FastMem.LOW_WORD(obj2_addr, out child);
                FastMem.SET_WORD(obj2_addr, obj1);
                obj1_addr += (zword)(O4_SIBLING - O4_PARENT);
                FastMem.SET_WORD(obj1_addr, child);
            }
        }/* z_insert_obj */
예제 #30
0
        }/* z_get_parent */

        /*
         * z_get_prop, store the value of an object property.
         *
         *	Process.zargs[0] = object
         *	Process.zargs[1] = number of property to be examined
         *
         */

        internal static void z_get_prop()
        {
            zword prop_addr;
            zword wprop_val;
            zbyte bprop_val;
            zbyte value;
            zbyte mask;

            if (Process.zargs[0] == 0)
            {
                Err.runtime_error(ErrorCodes.ERR_GET_PROP_0);
                Process.store(0);
                return;
            }

            /* Property id is in bottom five (six) bits */

            mask = (zbyte)((main.h_version <= ZMachine.V3) ? 0x1f : 0x3f);

            /* Load address of first property */

            prop_addr = first_property(Process.zargs[0]);

            /* Scan down the property list */

            for (; ;)
            {
                FastMem.LOW_BYTE(prop_addr, out value);
                if ((value & mask) <= Process.zargs[1])
                {
                    break;
                }
                prop_addr = next_property(prop_addr);
            }

            if ((value & mask) == Process.zargs[1])     /* property found */

            /* Load property (byte or word sized) */

            {
                prop_addr++;

                if ((main.h_version <= ZMachine.V3 && !((value & 0xe0) > 0)) || (main.h_version >= ZMachine.V4 && !((value & 0xc0) > 0)))
                {
                    FastMem.LOW_BYTE(prop_addr, out bprop_val);
                    wprop_val = bprop_val;
                }
                else
                {
                    FastMem.LOW_WORD(prop_addr, out wprop_val);
                }
            }
            else        /* property not found */

            /* Load default value */

            {
                prop_addr = (zword)(main.h_objects + 2 * (Process.zargs[1] - 1));
                FastMem.LOW_WORD(prop_addr, out wprop_val);
            }

            /* Store the property value */

            Process.store(wprop_val);
        }/* z_get_prop */