コード例 #1
0
ファイル: process.cs プロジェクト: ChrisJamesSadler/IL2CPU
        }/* z_check_arg_count */

        /*
         * z_jump, jump unconditionally to the given address.
         *
         *	zargs[0] = PC relative address
         *
         */

        internal static void z_jump()
        {
            long pc;

            FastMem.GET_PC(out pc);

            pc += (short)zargs[0] - 2; // TODO This actually counts on an overflow to work

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

            FastMem.SET_PC(pc);
        }/* z_jump */
コード例 #2
0
ファイル: process.cs プロジェクト: ChrisJamesSadler/IL2CPU
        }/* ret */

        /*
         * branch
         *
         * Take a jump after an instruction based on the flag, either true or
         * false. The branch can be short or long; it is encoded in one or two
         * bytes respectively. When bit 7 of the first byte is set, the jump
         * takes place if the flag is true; otherwise it is taken if the flag
         * is false. When bit 6 of the first byte is set, the branch is short;
         * otherwise it is long. The offset occupies the bottom 6 bits of the
         * first byte plus all the bits in the second byte for long branches.
         * Uniquely, an offset of 0 means return false, and an offset of 1 is
         * return true.
         *
         */

        internal static void branch(bool flag)
        {
            long  pc;
            zword offset;
            zbyte specifier;
            zbyte off1;
            zbyte off2;

            FastMem.CODE_BYTE(out specifier);

            off1 = (zbyte)(specifier & 0x3f);

            if (!flag)
            {
                specifier ^= 0x80;
            }

            if ((specifier & 0x40) == 0)
            {                          // if (!(specifier & 0x40)) {		/* it's a long branch */
                if ((off1 & 0x20) > 0) /* propagate sign bit */
                {
                    off1 |= 0xc0;
                }

                FastMem.CODE_BYTE(out off2);

                offset = (zword)((off1 << 8) | off2);
            }
            else
            {
                offset = off1;          /* it's a short branch */
            }
            if ((specifier & 0x80) > 0)
            {
                if (offset > 1)
                {               /* normal branch */
                    FastMem.GET_PC(out pc);
                    pc += (short)offset - 2;
                    FastMem.SET_PC(pc);
                }
                else
                {
                    ret(offset);                /* special case, return 0 or 1 */
                }
            }
        }/* branch */
コード例 #3
0
ファイル: err.cs プロジェクト: ChrisJamesSadler/IL2CPU
        /*
         * runtime_error
         *
         * An error has occurred. Ignore it, pass it to os_fatal or report
         * it according to err_report_mode.
         *
         * errnum : Numeric code for error (1 to ERR_NUM_ERRORS)
         *
         */

        internal static void runtime_error(int errnum)
        {
            bool wasfirst;

            if (errnum <= 0 || errnum > ErrorCodes.ERR_NUM_ERRORS)
            {
                return;
            }

            if (err_report_mode == ErrorCodes.ERR_REPORT_FATAL ||
                (main.option_ignore_errors == false && errnum <= ErrorCodes.ERR_MAX_FATAL))
            {
                Buffer.flush_buffer();
                os_.fatal(err_messages[errnum - 1]);
                return;
            }

            wasfirst = (error_count[errnum - 1] == 0);
            error_count[errnum - 1]++;

            if ((err_report_mode == ErrorCodes.ERR_REPORT_ALWAYS) ||
                (err_report_mode == ErrorCodes.ERR_REPORT_ONCE && wasfirst))
            {
                long pc;

                FastMem.GET_PC(out pc);
                Text.print_string("Warning: ");
                Text.print_string(err_messages[errnum - 1]);
                Text.print_string(" (PC = ");
                print_long(pc, 16);
                Buffer.print_char(')');

                if (err_report_mode == ErrorCodes.ERR_REPORT_ONCE)
                {
                    Text.print_string(" (will ignore further occurrences)");
                }
                else
                {
                    Text.print_string(" (occurence ");
                    print_long(error_count[errnum - 1], 10);
                    Buffer.print_char(')');
                }
                Buffer.new_line();
            }
        } /* report_error */
コード例 #4
0
ファイル: process.cs プロジェクト: ChrisJamesSadler/IL2CPU
        }/* 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 */
コード例 #5
0
ファイル: quetzal.cs プロジェクト: gvsurenderreddy/Cosmos
        /*
         * Save a game using Quetzal format. Return 1 if OK, 0 if failed.
         */

        internal static zword save_quetzal(FileStream svf, MemoryStream stf)
        {
            zlong ifzslen = 0, cmemlen = 0, stkslen = 0;
            long  pc;
            zword i, j, n;
            int   nvars, nargs, nstk, p;
            zbyte var;
            long  cmempos, stkspos;
            int   c;

            /* Write `IFZS' header. */
            if (!write_chnk(svf, ID_FORM, 0))
            {
                return(0);
            }
            if (!write_long(svf, ID_IFZS))
            {
                return(0);
            }

            /* Write `IFhd' chunk. */
            FastMem.GET_PC(out pc);
            if (!write_chnk(svf, ID_IFhd, 13))
            {
                return(0);
            }
            if (!write_word(svf, main.h_release))
            {
                return(0);
            }
            for (i = ZMachine.H_SERIAL; i < ZMachine.H_SERIAL + 6; ++i)
            {
                if (!write_byte(svf, FastMem.ZMData[FastMem.zmp + i]))
                {
                    return(0);
                }
            }
            if (!write_word(svf, main.h_checksum))
            {
                return(0);
            }
            if (!write_long(svf, pc << 8)) /* Includes pad. */ return {
                (0);
            }

            /* Write `CMem' chunk. */
            if ((cmempos = svf.Position) < 0)
            {
                return(0);
            }
            if (!write_chnk(svf, ID_CMem, 0))
            {
                return(0);
            }
            // (void) fseek (stf, 0, SEEK_SET);
            stf.Position = 0;
            /* j holds current run length. */
            for (i = 0, j = 0, cmemlen = 0; i < main.h_dynamic_size; ++i)
            {
                if ((c = stf.ReadByte()) == -1)
                {
                    return(0);
                }
                c ^= (int)FastMem.ZMData[i];
                if (c == 0)
                {
                    ++j;        /* It's a run of equal bytes. */
                }
                else
                {
                    /* Write out any run there may be. */
                    if (j > 0)
                    {
                        for (; j > 0x100; j -= 0x100)
                        {
                            if (!write_run(svf, 0xFF))
                            {
                                return(0);
                            }
                            cmemlen += 2;
                        }
                        if (!write_run(svf, (byte)(j - 1)))
                        {
                            return(0);
                        }
                        cmemlen += 2;
                        j        = 0;
                    }
                    /* Any runs are now written. Write this (nonzero) byte. */
                    if (!write_byte(svf, (zbyte)c))
                    {
                        return(0);
                    }
                    ++cmemlen;
                }
            }

            /*
             * Reached end of dynamic memory. We ignore any unwritten run there may be
             * at this point.
             */
            if ((cmemlen & 1) > 0)      /* Chunk length must be even. */
            {
                if (!write_byte(svf, 0))
                {
                    return(0);
                }
            }

            /* Write `Stks' chunk. You are not expected to understand this. ;) */
            if ((stkspos = svf.Position) < 0)
            {
                return(0);
            }
            if (!write_chnk(svf, ID_Stks, 0))
            {
                return(0);
            }

            /*
             * We construct a list of frame indices, most recent first, in `frames'.
             * These indices are the offsets into the `stack' array of the word before
             * the first word pushed in each frame.
             */
            frames[0] = (zword)main.sp; /* The frame we'd get by doing a call now. */
            for (i = (zword)(main.fp + 4), n = 0; i < General.STACK_SIZE + 4; i = (zword)(main.stack[i - 3] + 5))
            {
                frames[++n] = i;
            }

            /*
             * All versions other than V6 can use evaluation stack outside a function
             * context. We write a faked stack frame (most fields zero) to cater for
             * this.
             */
            if (main.h_version != ZMachine.V6)
            {
                for (i = 0; i < 6; ++i)
                {
                    if (!write_byte(svf, 0))
                    {
                        return(0);
                    }
                }
                nstk = General.STACK_SIZE - frames[n];
                if (!write_word(svf, nstk))
                {
                    return(0);
                }
                for (j = (zword)(General.STACK_SIZE - 1); j >= frames[n]; --j)
                {
                    if (!write_word(svf, main.stack[j]))
                    {
                        return(0);
                    }
                }
                stkslen = (zword)(8 + 2 * nstk);
            }

            /* Write out the rest of the stack frames. */
            for (i = n; i > 0; --i)
            {
                p     = frames[i] - 4; // p = stack + frames[i] - 4;	/* Points to call frame. */
                nvars = (main.stack[p] & 0x0F00) >> 8;
                nargs = main.stack[p] & 0x00FF;
                nstk  = (zword)(frames[i] - frames[i - 1] - nvars - 4);
                pc    = ((zlong)main.stack[p + 3] << 9) | main.stack[p + 2];

                switch (main.stack[p] & 0xF000) /* Check type of call. */
                {
                case 0x0000:                    /* Function. */
                    var = FastMem.ZMData[FastMem.zmp + pc];
                    pc  = ((pc + 1) << 8) | (zlong)nvars;
                    break;

                case 0x1000:                               /* Procedure. */
                    var = 0;
                    pc  = (pc << 8) | 0x10 | (zlong)nvars; /* Set procedure flag. */
                    break;

                /* case 0x2000: */
                default:
                    Err.runtime_error(ErrorCodes.ERR_SAVE_IN_INTER);
                    return(0);
                }
                if (nargs != 0)
                {
                    nargs = (zword)((1 << nargs) - 1);  /* Make args into bitmap. */
                }
                /* Write the main part of the frame... */
                if (!write_long(svf, pc) ||
                    !write_byte(svf, var) ||
                    !write_byte(svf, nargs) ||
                    !write_word(svf, nstk))
                {
                    return(0);
                }

                /* Write the variables and eval stack. */
                for (j = 0, --p; j < nvars + nstk; ++j, --p)
                {
                    if (!write_word(svf, main.stack[p]))
                    {
                        return(0);
                    }
                }

                /* Calculate length written thus far. */
                stkslen += (zword)(8 + 2 * (nvars + nstk));
            }

            /* Fill in variable chunk lengths. */
            ifzslen = 3 * 8 + 4 + 14 + cmemlen + stkslen;
            if ((cmemlen & 1) > 0)
            {
                ++ifzslen;
            }
            svf.Position = 4;
            if (!write_long(svf, ifzslen))
            {
                return(0);
            }
            svf.Position = cmempos + 4;
            if (!write_long(svf, cmemlen))
            {
                return(0);
            }
            svf.Position = stkspos + 4;
            if (!write_long(svf, stkslen))
            {
                return(0);
            }

            /* After all that, still nothing went wrong! */
            return(1);
        }