internal ZDictionary(Story story, ZText ztext) { this.story = story; this.ztext = ztext; this.address = Header.ReadDictionaryAddress(story.Memory); var reader = new MemoryReader(story.Memory, address); int wordSepCount = reader.NextByte(); this.wordSeparators = reader.NextBytes(wordSepCount).ConvertAll(b => (char)b).AsReadOnly(); int entryLength = reader.NextByte(); int entryCount = reader.NextWord(); int zwordsSize = story.Version <= 3 ? 2 : 3; int dataSize = entryLength - (zwordsSize * 2); this.entries = new List <ZDictionaryEntry>(entryCount); for (int i = 0; i < entryCount; i++) { var entryAddress = reader.Address; var entryZWords = reader.NextWords(zwordsSize); var entryData = reader.NextBytes(dataSize); var entryZText = ztext.ZWordsAsString(entryZWords, ZTextFlags.All); entries.Add(new ZDictionaryEntry(entryAddress, i, entryZWords, entryZText, entryData)); } }
public void NextWordWorksAsExpectedFromDifferentIndex() { byte[] bytes = { 0xff, 0x00, 0x0f, 0xf0, 0xff, 0x00, 0x0f, 0xf0, 0xff, 0x00, 0x0f, 0xf0, 0xff, 0x00, 0x0f, 0xf0 }; var reader = new MemoryReader(bytes, 8); ushort[] expected = { 0xff00, 0x0ff0, 0xff00, 0x0ff0, 0xff00, 0x0ff0, 0xff00, 0x0ff0 }; for (int i = 4; i < expected.Length; i++) { var w = reader.NextWord(); Assert.That(w, Is.EqualTo(expected[i])); } Assert.That(reader.Address, Is.EqualTo(reader.Size)); Assert.That(() => reader.NextWord(), Throws.InstanceOf <InvalidOperationException>()); }
//private void MemoryChanged(object sender, MemoryEventArgs e) //{ // // Replace affected lines // int firstLineIndex = e.Address / 16; // int lastLineIndex = (e.Address + e.Length) / 16; // var reader = e.Memory.CreateReader(firstLineIndex * 16); // for (int i = firstLineIndex; i <= lastLineIndex; i++) // { // var address = reader.Address; // var count = Math.Min(8, reader.RemainingBytes); // var values = reader.NextWords(count); // lines[i] = new MemoryLineViewModel(address, values); // } // // TODO: Highlight modified memory //} private void StoryService_StoryOpened(object sender, StoryOpenedEventArgs e) { var reader = new MemoryReader(e.Story.Memory, 0); lines.BeginBulkOperation(); try { while (reader.RemainingBytes > 0) { var address = reader.Address; ushort[] values; if (reader.RemainingBytes >= 16 || reader.RemainingBytes % 2 == 0) { var count = Math.Min(8, reader.RemainingBytes / 2); values = reader.NextWords(count); } else { // if the last line is an odd number of bytes... // TODO: memory view always shows even number of bytes // (padding with zeroes if necessry). Need to fix it to show odd // number of bytes if that's the case. var valueList = new List <ushort>(); while (reader.RemainingBytes > 0) { if (reader.RemainingBytes > 2) { valueList.Add(reader.NextWord()); } else { valueList.Add((ushort)(reader.NextByte() << 8)); } } values = valueList.ToArray(); } lines.Add(new MemoryLineViewModel(address, values)); } } finally { lines.EndBulkOperation(); } PropertyChanged("HasStory"); }
public BlorbFile(Stream stream) { if (stream == null) { throw new ArgumentNullException("stream"); } this.memory = stream.ReadFully(); var reader = new MemoryReader(this.memory, 0); var dwords = reader.NextDWords(3); // First, ensure that this is a valid format if (dwords[0] != id_FORM) { throw new InvalidOperationException(); } if (dwords[2] != id_IFRS) { throw new InvalidOperationException(); } int totalLength = (int)dwords[1] + 8; // Collect all chunks this.chunks = new List <ChunkDescriptor>(); while (reader.Address < totalLength) { var chunk = new ChunkDescriptor(); chunk.Address = (uint)reader.Address; var type = reader.NextDWord(); var len = reader.NextDWord(); chunk.Type = type; if (type == id_FORM) { chunk.DataAddress = chunk.Address; chunk.Length = len + 8; } else { chunk.DataAddress = (uint)reader.Address; chunk.Length = len; } chunks.Add(chunk); reader.Skip((int)len); if ((reader.Address & 1) != 0) { reader.Skip(1); } if (reader.Address > totalLength) { throw new InvalidOperationException(); } } // Loop through chunks and collect resources this.resources = new List <ResourceDecriptor>(); foreach (var chunk in chunks) { if (chunk.Type == id_RIdx) { reader.Address = (int)chunk.DataAddress; var numResources = (int)reader.NextDWord(); if (chunk.Length < (numResources * 12) + 4) { throw new InvalidOperationException(); } for (int i = 0; i < numResources; i++) { var resource = new ResourceDecriptor(); resource.Usage = reader.NextDWord(); resource.Number = reader.NextDWord(); var resourcePos = reader.NextDWord(); var chunkIndex = chunks.FindIndex(c => c.Address == resourcePos); if (chunkIndex < 0) { throw new InvalidOperationException(); } resource.ChunkNumber = chunkIndex; resources.Add(resource); } } else if (chunk.Type == id_RelN) { reader.Address = (int)chunk.DataAddress; if (chunk.Length < 2) { throw new InvalidOperationException(); } releaseNumber = reader.NextWord(); } else if (chunk.Type == id_IFhd) { reader.Address = (int)chunk.DataAddress; if (chunk.Length < 3) { throw new InvalidOperationException(); } var header = new ZHeader(); header.ReleaseNumber = reader.NextWord(); header.SerialNumber = new char[6]; for (int i = 0; i < 6; i++) { header.SerialNumber[i] = (char)reader.NextByte(); } header.Checksum = reader.NextWord(); } else if (chunk.Type == id_Reso) { } else if (chunk.Type == id_Loop) { } else if (chunk.Type == id_Plte) { } } }