Exemple #1
0
        /*
         * load_operand
         *
         * Load an operand, either a variable or a constant.
         *
         */

        static void load_operand(zbyte type)
        {
            zword value;

            if ((type & 2) > 0)
            {                   /* variable */
                zbyte variable;

                FastMem.CODE_BYTE(out variable);

                if (variable == 0)
                {
                    value = main.stack[main.sp++];
                }
                else if (variable < 16)
                {
                    value = main.stack[main.fp - variable];
                }
                else
                {
                    zword addr = (zword)(main.h_globals + 2 * (variable - 16)); // TODO Make sure this logic
                    FastMem.LOW_WORD(addr, out value);
                }
            }
            else if ((type & 1) > 0)
            {           /* small constant */
                zbyte bvalue;

                FastMem.CODE_BYTE(out bvalue);
                value = bvalue;
            }
            else
            {
                FastMem.CODE_WORD(out value);           /* large constant */
            }
            zargs[zargc++] = value;

            DebugState.Output("  Storing operand: {0} -> {1}", zargc - 1, value);
        }/* load_operand */
Exemple #2
0
        }/* interpret */

        /*
         * call
         *
         * Call a subroutine. Save PC and FP then load new PC and initialise
         * new stack frame. Note that the caller may legally provide less or
         * more arguments than the function actually has. The call type "ct"
         * can be 0 (z_call_s), 1 (z_call_n) or 2 (direct call).
         *
         */

        internal static void call(zword routine, int argc, int args_offset, int ct)
        {
            long  pc;
            zword value;
            zbyte count;
            int   i;

            if (main.sp < 4)//if (sp - stack < 4)
            {
                Err.runtime_error(ErrorCodes.ERR_STK_OVF);
            }

            FastMem.GET_PC(out pc);

            main.stack[--main.sp] = (zword)(pc >> 9);
            main.stack[--main.sp] = (zword)(pc & 0x1ff);
            main.stack[--main.sp] = (zword)(main.fp - 1); // *--sp = (zword) (fp - stack - 1);
            main.stack[--main.sp] = (zword)(argc | (ct << (main.option_save_quetzal == true ? 12 : 8)));

            main.fp = main.sp;
            main.frame_count++;

            DebugState.Output("Added Frame: {0} -> {1}:{2}:{3}:{4}",
                              main.frame_count,
                              main.stack[main.sp + 0],
                              main.stack[main.sp + 1],
                              main.stack[main.sp + 2],
                              main.stack[main.sp + 3]);

            /* Calculate byte address of routine */

            if (main.h_version <= ZMachine.V3)
            {
                pc = (long)routine << 1;
            }
            else if (main.h_version <= ZMachine.V5)
            {
                pc = (long)routine << 2;
            }
            else if (main.h_version <= ZMachine.V7)
            {
                pc = ((long)routine << 2) + ((long)main.h_functions_offset << 3);
            }
            else /* (h_version <= V8) */
            {
                pc = (long)routine << 3;
            }

            if (pc >= main.story_size)
            {
                Err.runtime_error(ErrorCodes.ERR_ILL_CALL_ADDR);
            }

            FastMem.SET_PC(pc);

            /* Initialise local variables */

            FastMem.CODE_BYTE(out count);

            if (count > 15)
            {
                Err.runtime_error(ErrorCodes.ERR_CALL_NON_RTN);
            }
            if (main.sp < count)
            {
                Err.runtime_error(ErrorCodes.ERR_STK_OVF);
            }

            if (main.option_save_quetzal == true)
            {
                main.stack[main.fp] |= (zword)(count << 8);     /* Save local var count for Quetzal. */
            }
            value = 0;

            for (i = 0; i < count; i++)
            {
                if (main.h_version <= ZMachine.V4)              /* V1 to V4 games provide default */
                {
                    FastMem.CODE_WORD(out value);               /* values for all local variables */
                }
                main.stack[--main.sp] = (zword)((argc-- > 0) ? zargs[args_offset + i] : value);
                //*--sp = (zword) ((argc-- > 0) ? args[i] : value);
            }

            /* Start main loop for direct calls */

            if (ct == 2)
            {
                interpret();
            }
        }/* call */
Exemple #3
0
        static void decode_text(string_type st, zword addr)
        {
            // zword* ptr;
            long  byte_addr;
            zword c2;
            zword code;
            zbyte c, prev_c = 0;
            int   shift_state = 0;
            int   shift_lock  = 0;
            int   status      = 0;

            // ptr = NULL;		/* makes compilers shut up */
            byte_addr = 0;

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

            /* Calculate the byte address if necessary */

            if (st == string_type.ABBREVIATION)
            {
                byte_addr = (long)addr << 1;
            }

            else if (st == string_type.HIGH_STRING)
            {
                if (main.h_version <= ZMachine.V3)
                {
                    byte_addr = (long)addr << 1;
                }
                else if (main.h_version <= ZMachine.V5)
                {
                    byte_addr = (long)addr << 2;
                }
                else if (main.h_version <= ZMachine.V7)
                {
                    byte_addr = ((long)addr << 2) + ((long)main.h_strings_offset << 3);
                }
                else /* (h_version <= V8) */
                {
                    byte_addr = (long)addr << 3;
                }

                if (byte_addr >= main.story_size)
                {
                    Err.runtime_error(ErrorCodes.ERR_ILL_PRINT_ADDR);
                }
            }

            /* Loop until a 16bit word has the highest bit set */
            if (st == string_type.VOCABULARY)
            {
                ptrDt = 0;
            }

            do
            {
                int i;

                /* Fetch the next 16bit word */

                if (st == string_type.LOW_STRING || st == string_type.VOCABULARY)
                {
                    FastMem.LOW_WORD(addr, out code);
                    addr += 2;
                }
                else if (st == string_type.HIGH_STRING || st == string_type.ABBREVIATION)
                {
                    FastMem.HIGH_WORD(byte_addr, out code);
                    byte_addr += 2;
                }
                else
                {
                    FastMem.CODE_WORD(out code);
                }

                /* Read its three Z-characters */

                for (i = 10; i >= 0; i -= 5)
                {
                    zword abbr_addr;
                    zword ptr_addr;
                    zword zc;

                    c = (zbyte)((code >> i) & 0x1f);

                    switch (status)
                    {
                    case 0:     /* normal operation */

                        if (shift_state == 2 && c == 6)
                        {
                            status = 2;
                        }

                        else if (main.h_version == ZMachine.V1 && c == 1)
                        {
                            Buffer.new_line();
                        }

                        else if (main.h_version >= ZMachine.V2 && shift_state == 2 && c == 7)
                        {
                            Buffer.new_line();
                        }

                        else if (c >= 6)
                        {
                            outchar(st, alphabet(shift_state, c - 6));
                        }

                        else if (c == 0)
                        {
                            outchar(st, ' ');
                        }

                        else if (main.h_version >= ZMachine.V2 && c == 1)
                        {
                            status = 1;
                        }

                        else if (main.h_version >= ZMachine.V3 && c <= 3)
                        {
                            status = 1;
                        }

                        else
                        {
                            shift_state = (shift_lock + (c & 1) + 1) % 3;

                            if (main.h_version <= ZMachine.V2 && c >= 4)
                            {
                                shift_lock = shift_state;
                            }

                            break;
                        }

                        shift_state = shift_lock;

                        break;

                    case 1:     /* abbreviation */

                        ptr_addr = (zword)(main.h_abbreviations + 64 * (prev_c - 1) + 2 * c);

                        FastMem.LOW_WORD(ptr_addr, out abbr_addr);
                        decode_text(string_type.ABBREVIATION, abbr_addr);

                        status = 0;
                        break;

                    case 2:     /* ZSCII character - first part */

                        status = 3;
                        break;

                    case 3:     /* ZSCII character - second part */

                        zc = (zword)((prev_c << 5) | c);

                        c2 = translate_from_zscii((zbyte)zc);     // TODO This doesn't seem right
                        outchar(st, c2);

                        status = 0;
                        break;
                    }

                    prev_c = c;
                }
            } while (!((code & 0x8000) > 0));

            if (st == string_type.VOCABULARY)
            {
                ptrDt = 0;
            }
        }/* decode_text */