internal static void ScriptOpen() { unchecked { Main.h_flags &= (zword) ~ZMachine.SCRIPTING_FLAG; } if (Main.h_version >= ZMachine.V5 || !ScriptValid) { if (!OS.ReadFileName(out string?new_name, General.DEFAULT_SCRIPT_NAME, FileTypes.FILE_SCRIPT)) { goto done; } ScriptName = new_name; } if ((Sfp = new System.IO.StreamWriter(ScriptName, true)) != null) { Main.h_flags |= ZMachine.SCRIPTING_FLAG; ScriptValid = true; Main.ostream_script = true; ScriptWidth = 0; Sfp.AutoFlush = true; } else { Text.PrintString("Cannot open file\n"); } done: FastMem.SetWord(ZMachine.H_FLAGS, Main.h_flags); }/* script_open */
}/* 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 ZInsertObj() { 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.StreamMssgOn(); Text.PrintString("@move_obj "); Text.PrintObject(obj1); Text.PrintString(" "); Text.PrintObject(obj2); Stream.StreamMssgOff(); } if (obj1 == 0) { Err.RuntimeError(ErrorCodes.ERR_MOVE_OBJECT_0); return; } if (obj2 == 0) { Err.RuntimeError(ErrorCodes.ERR_MOVE_OBJECT_TO_0); return; } /* Get addresses of both objects */ obj1_addr = ObjectAddress(obj1); obj2_addr = ObjectAddress(obj2); /* Remove object 1 from current parent */ UnlinkObject(obj1); /* Make object 1 first child of object 2 */ if (Main.h_version <= ZMachine.V3) { obj1_addr += O1_PARENT; FastMem.SetByte(obj1_addr, (zbyte)obj2); obj2_addr += O1_CHILD; FastMem.LowByte(obj2_addr, out byte child); FastMem.SetByte(obj2_addr, (zbyte)obj1); obj1_addr += (zword)(O1_SIBLING - O1_PARENT); FastMem.SetByte(obj1_addr, child); } else { obj1_addr += O4_PARENT; FastMem.SetWord(obj1_addr, obj2); obj2_addr += O4_CHILD; FastMem.LowWord(obj2_addr, out ushort child); FastMem.SetWord(obj2_addr, obj1); obj1_addr += (zword)(O4_SIBLING - O4_PARENT); FastMem.SetWord(obj1_addr, child); } }/* z_insert_obj */
}/* memory_word */ /* * memory_close * * End of output redirection. * */ internal static void MemoryClose() { if (depth >= 0) { if (redirect[depth].XSize != 0xffff) { MemoryNewline(); } if (Main.h_version == ZMachine.V6) { Main.h_line_width = (redirect[depth].XSize != 0xffff) ? redirect[depth].Total : redirect[depth].Width; FastMem.SetWord(ZMachine.H_LINE_WIDTH, Main.h_line_width); } if (depth == 0) { Main.ostream_memory = false; } depth--; } }/* memory_close */
}/* script_open */ /* * script_close * * Stop transscription. * */ internal static void ScriptClose() { unchecked { Main.h_flags &= (ushort)~ZMachine.SCRIPTING_FLAG; } FastMem.SetWord(ZMachine.H_FLAGS, Main.h_flags); Sfp?.Close(); Main.ostream_script = false; }/* script_close */
}/* 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 ZPutProp() { zword prop_addr; zbyte value; zbyte mask; if (Process.zargs[0] == 0) { Err.RuntimeError(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 = FirstProperty(Process.zargs[0]); /* Scan down the property list */ for (; ;) { FastMem.LowByte(prop_addr, out value); if ((value & mask) <= Process.zargs[1]) { break; } prop_addr = NextProperty(prop_addr); } /* Exit if the property does not exist */ if ((value & mask) != Process.zargs[1]) { Err.RuntimeError(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.SetByte(prop_addr, v); } else { zword v = Process.zargs[2]; FastMem.SetWord(prop_addr, v); } }/* z_put_prop */
}/* z_pop_stack */ /* * z_pull, pop a value off... * * a) ...the game or a user stack and store it (V6) * * zargs[0] = address of user stack (optional) * * b) ...the game stack and write it to a variable (other than V6) * * zargs[0] = variable to write value to * */ internal static void ZPull() { zword value; if (Main.h_version != ZMachine.V6) { /* not a V6 game, pop stack and write */ value = Main.Stack[Main.sp++]; if (Process.zargs[0] == 0) { Main.Stack[Main.sp] = value; } else if (Process.zargs[0] < 16) { // *(fp - Process.zargs[0]) = value; Main.Stack[Main.fp - Process.zargs[0]] = value; } else { zword addr = (zword)(Main.h_globals + 2 * (Process.zargs[0] - 16)); FastMem.SetWord(addr, value); } } else { /* it's V6, but is there a user stack? */ if (Process.zargc == 1) { /* it's a user stack */ zword addr = Process.zargs[0]; FastMem.LowWord(addr, out ushort size); size++; FastMem.StoreW(addr, size); addr += (zword)(2 * size); FastMem.LowWord(addr, out value); } else { value = Main.Stack[Main.sp++];// value = *sp++; /* it's the game stack */ } Process.Store(value); } }/* z_pull */
}/* z_dec_chk */ /* * z_inc, increment a variable. * * zargs[0] = variable to increment * */ internal static void ZInc() { if (Process.zargs[0] == 0) { Main.Stack[Main.sp]++; // (*sp)++; } else if (Process.zargs[0] < 16) { (Main.Stack[Main.fp - Process.zargs[0]])++; } else { zword addr = (zword)(Main.h_globals + 2 * (Process.zargs[0] - 16)); FastMem.LowWord(addr, out ushort value); value++; FastMem.SetWord(addr, value); } }/* z_inc */
/* * z_dec, decrement a variable. * * zargs[0] = variable to decrement * */ internal static void ZDec() { if (Process.zargs[0] == 0) { Main.Stack[Main.sp]--; } else if (Process.zargs[0] < 16) { Main.Stack[Main.fp - Process.zargs[0]]--; } else { zword addr = (zword)(Main.h_globals + 2 * (Process.zargs[0] - 16)); FastMem.LowWord(addr, out ushort value); value--; FastMem.SetWord(addr, value); } }/* z_dec */
}/* z_push_stack */ /* * z_store, write a value to a variable. * * zargs[0] = variable to be written to * zargs[1] = value to write * */ internal static void ZStore() { zword value = Process.zargs[1]; if (Process.zargs[0] == 0) { Main.Stack[Main.sp] = value; } else if (Process.zargs[0] < 16) { Main.Stack[Main.fp - Process.zargs[0]] = value; } else { zword addr = (zword)(Main.h_globals + 2 * (Process.zargs[0] - 16)); FastMem.SetWord(addr, value); } }/* z_store */
}/* z_dec */ /* * z_dec_chk, decrement a variable and branch if now less than value. * * zargs[0] = variable to decrement * zargs[1] = value to check variable against * */ internal static void ZDecChk() { zword value; if (Process.zargs[0] == 0) { value = --Main.Stack[Main.sp]; } else if (Process.zargs[0] < 16) { value = --Main.Stack[Main.fp - Process.zargs[0]]; } else { zword addr = (zword)(Main.h_globals + 2 * (Process.zargs[0] - 16)); FastMem.LowWord(addr, out value); value--; FastMem.SetWord(addr, value); } Process.Branch((short)value < (short)Process.zargs[1]); }/* z_dec_chk */
}/* next_property */ /* * unlink_object * * Unlink an object from its parent and siblings. * */ private static void UnlinkObject(zword object_var) { zword parent_addr; zword sibling_addr; if (object_var == 0) { Err.RuntimeError(ErrorCodes.ERR_REMOVE_OBJECT_0); return; } zword obj_addr = ObjectAddress(object_var); if (Main.h_version <= ZMachine.V3) { zbyte zero = 0; /* Get parent of object, and return if no parent */ obj_addr += O1_PARENT; FastMem.LowByte(obj_addr, out byte parent); if (parent == 0) { return; } /* Get (older) sibling of object and set both parent and sibling * pointers to 0 */ FastMem.SetByte(obj_addr, zero); obj_addr += (zword)(O1_SIBLING - O1_PARENT); FastMem.LowByte(obj_addr, out byte older_sibling); FastMem.SetByte(obj_addr, zero); /* Get first child of parent (the youngest sibling of the object) */ parent_addr = (zword)(ObjectAddress(parent) + O1_CHILD); FastMem.LowByte(parent_addr, out byte younger_sibling); /* Remove object from the list of siblings */ if (younger_sibling == object_var) { FastMem.SetByte(parent_addr, older_sibling); } else { do { sibling_addr = (zword)(ObjectAddress(younger_sibling) + O1_SIBLING); FastMem.LowByte(sibling_addr, out younger_sibling); } while (younger_sibling != object_var); FastMem.SetByte(sibling_addr, older_sibling); } } else { zword zero = 0; /* Get parent of object, and return if no parent */ obj_addr += O4_PARENT; FastMem.LowWord(obj_addr, out zword parent); if (parent == 0) { return; } /* Get (older) sibling of object and set both parent and sibling * pointers to 0 */ FastMem.SetWord(obj_addr, zero); obj_addr += (zword)(O4_SIBLING - O4_PARENT); FastMem.LowWord(obj_addr, out ushort older_sibling); FastMem.SetWord(obj_addr, zero); /* Get first child of parent (the youngest sibling of the object) */ parent_addr = (zword)(ObjectAddress(parent) + O4_CHILD); FastMem.LowWord(parent_addr, out ushort younger_sibling); /* Remove object from the list of siblings */ if (younger_sibling == object_var) { FastMem.SetWord(parent_addr, older_sibling); } else { do { sibling_addr = (zword)(ObjectAddress(younger_sibling) + O4_SIBLING); FastMem.LowWord(sibling_addr, out younger_sibling); } while (younger_sibling != object_var); FastMem.SetWord(sibling_addr, older_sibling); } } }/* unlink_object */