/// <summary> /// Calls a routine. /// </summary> /// <param name="routineType"> /// The routine type. /// </param> /// <param name="packedAddress"> /// The packed address of the routine. /// </param> /// <param name="arguments"> /// Routine arguments. /// </param> protected void CallRoutine(RoutineType routineType, ushort packedAddress, ImmutableStack<ushort> arguments) { if (packedAddress == 0) { this.Return(0, routineType); return; } var argumentCount = (byte)arguments.Count(); var programCounter = this.UnpackRoutineAddress(packedAddress); var localVariableCount = this.Memory.ReadByte(programCounter); if (localVariableCount > MaximumLocalVariables) { this.FrontEnd.ErrorNotification(ErrorCondition.InvalidRoutine, "Called a routine at address " + programCounter + " with " + localVariableCount + " local variables."); } this.CallStack.BeginRoutine(routineType, programCounter + 1, argumentCount, localVariableCount); this.InitializeLocalVariables(localVariableCount); byte localVariableNumber = 0; foreach (var argument in arguments.Enumerable()) { if (localVariableNumber >= localVariableCount) { break; } this.CallStack.WriteLocalVariable(localVariableNumber++, argument); } }
/// <summary> /// Compares a dictionary entry to a word. /// </summary> /// <param name="dictionaryEntryAddress"> /// The dictionary entry address. /// </param> /// <param name="encodedWord"> /// The encoded word. /// </param> /// <returns> /// Returns 0 if the entry and word are equal, -1 if the entry comes before the word alphabetically and 1 if the entry comes after the word alphabetically. /// </returns> private int DictionaryCompare(int dictionaryEntryAddress, ImmutableStack<ushort> encodedWord) { var entryPosition = 0; foreach (var encodedValue in encodedWord.Enumerable()) { var entryPositionValue = this.Memory.ReadWord(dictionaryEntryAddress + entryPosition); if (entryPositionValue < encodedValue) { return -1; } if (entryPositionValue > encodedValue) { return 1; } entryPosition += 2; } return 0; }
/// <summary> /// Converts zscii text to unicode text. /// </summary> /// <param name="zsciiText"> /// The zscii text. /// </param> /// <returns> /// The unicode text. /// </returns> protected string ZsciiToUnicode(ImmutableStack<Zscii> zsciiText) { ImmutableStack<char> unicodeText = null; foreach (var zsciiCharacter in zsciiText.Enumerable()) { if (zsciiCharacter != Zscii.Null) { unicodeText = unicodeText.Add(this.ZsciiToUnicode(zsciiCharacter)); } } return unicodeText.Reverse().StackToString(); }
/// <summary> /// Gets the next word in the zscii text. /// </summary> /// <param name="zsciiText"> /// The zscii text. /// </param> /// <param name="wordSeparators"> /// The word separators. /// </param> /// <returns> /// The next word in the zscii text. /// </returns> private static ImmutableStack<Zscii> GetNextWord(ref ImmutableStack<Zscii> zsciiText, ImmutableStack<Zscii> wordSeparators) { ImmutableStack<Zscii> word = null; while (zsciiText != null) { var zsciiCharacter = zsciiText.Top; foreach (var wordSeparator in wordSeparators.Enumerable()) { if (zsciiCharacter == wordSeparator) { if (word == null) { word = word.Add(zsciiCharacter); zsciiText = zsciiText.Tail; } return word.Reverse(); } } word = word.Add(zsciiCharacter); zsciiText = zsciiText.Tail; } return word.Reverse(); }
/// <summary> /// Writes zscii text to memory. /// </summary> /// <param name="address"> /// The memory address to begin writing. /// </param> /// <param name="zsciiText"> /// The zscii text. /// </param> protected void WriteZsciiToMemory(int address, ImmutableStack<Zscii> zsciiText) { foreach (var zsciiCharacter in zsciiText.Enumerable()) { this.Memory.WriteByte(address++, (byte)zsciiCharacter); } }