private int SegmentLength(ChunkIterator iterator, int direction, int start) { var result = start; var owner = iterator.Here(); for (var i = 0; i < SymbolsNeeded - start; ++i) { var symbol = direction switch { 0 => iterator.Up(), 1 => iterator.UpRight(), 2 => iterator.Right(), 3 => iterator.DownRight(), 4 => iterator.Down(), 5 => iterator.DownLeft(), 6 => iterator.Left(), 7 => iterator.UpLeft(), _ => throw new ArgumentOutOfRangeException("internal error: direction does not exist") }; if (iterator.Here() != owner || ++result >= SymbolsNeeded) { break; } } iterator.Reset(); return(result); } }
private bool CheckDirection(ChunkIterator iterator, int direction) { var length = SegmentLength(iterator, direction, 1); if (length < SymbolsNeeded) { var opposite = (direction + 4) % 8; length = SegmentLength(iterator, opposite, length); } return(length >= SymbolsNeeded); }
Room ReadRoomCore(long offset, long chunkSize) { var objImages = new Dictionary<ushort, byte[]>(); var room = new Room { Size = (int)chunkSize }; var it = new ChunkIterator(_reader, chunkSize); while (it.MoveNext()) { switch (it.Current.Tag) { case "HD": // Room Header room.Header = ReadRMHD(); break; case "CC": // Color Cylcle room.ColorCycle = ReadCYCL(); break; case "SP": // EPAL ReadEPAL(); break; case "BX": // BOXD { var size = (int)(it.Current.Size - 6); var numBoxes = _reader.ReadByte(); var pos = _reader.BaseStream.Position; for (var i = 0; i < numBoxes; i++) { var box = ReadBox(); room.Boxes.Add(box); } size -= (int)(_reader.BaseStream.Position - pos); if (size > 0) { room.BoxMatrix.Clear(); room.BoxMatrix.AddRange(_reader.ReadBytes(size)); } } break; case "PA": { // Palette var colors = ReadCLUT(); room.HasPalette = true; Array.Copy(colors, room.Palette.Colors, colors.Length); } break; case "SA": // Scale if (it.Current.Size > 6) { room.Scales = ReadSCAL(); } break; case "BM": // Bitmap if (it.Current.Size > 6) { using (var ms = new MemoryStream(_reader.ReadBytes((int)(it.Current.Size - 6)))) { room.Image = ReadImage(ms, room.Header.Width / 8); } } break; case "EN": { // Entry script room.EntryScript.Data = _reader.ReadBytes((int)(it.Current.Size - 6)); } break; case "EX": { // Exit script room.ExitScript.Data = _reader.ReadBytes((int)(it.Current.Size - 6)); } break; case "LC": //LC { // *NLSC* number of local scripts var num = _reader.ReadUInt16(); } break; case "LS": { // local scripts var index = _reader.ReadByte(); var pos = _reader.BaseStream.Position; room.LocalScripts[index - 0xC8] = new ScriptData { Offset = pos - offset - 8, Data = _reader.ReadBytes((int)(it.Current.Size - 7)) }; } break; case "OI": { // Object Image var objId = _reader.ReadUInt16(); if (it.Current.Size > 8) { var img = _reader.ReadBytes((int)(it.Current.Size - 6)); objImages.Add(objId, img); } } break; case "OC": { // Object script var objId = _reader.ReadUInt16(); var t = _reader.ReadByte(); System.Diagnostics.Debug.WriteLine("objId={0}: {1}", objId, t); var x = _reader.ReadByte(); var tmp = _reader.ReadByte(); var y = tmp & 0x7F; byte parentState = (byte)(((tmp & 0x80) != 0) ? 1 : 0); var width = _reader.ReadByte(); var parent = _reader.ReadByte(); var walk_x = _reader.ReadInt16(); var walk_y = _reader.ReadInt16(); tmp = _reader.ReadByte(); byte height = (byte)(tmp & 0xF8); byte actordir = (byte)(tmp & 0x07); var data = new ObjectData(objId); data.Position = new Point((short)(8 * x), (short)(8 * y)); data.Width = (ushort)(8 * width); data.Height = height; data.Parent = parent; data.ParentState = parentState; data.Walk = new Point(walk_x, walk_y); data.ActorDir = actordir; room.Objects.Add(data); var nameOffset = _reader.ReadByte(); var size = nameOffset - 6 - 13; ReadVerbTable(data, size); data.Name = ReadObjectName(it, nameOffset); // read script size = (int)(it.Current.Offset + it.Current.Size - 6 - _reader.BaseStream.Position); data.Script.Data = _reader.ReadBytes(size); data.Script.Offset = nameOffset + data.Name.Length + 1; SetObjectImage(room.Image.ZPlanes.Count, objImages, data); } break; default: { var data = _reader.ReadBytes((int)it.Current.Size - 6); System.Diagnostics.Debug.WriteLine("Ignoring Resource Tag: {0} (0x{1:X2}{2:X2}) [{3}]", it.Current.Tag, (int)it.Current.Tag[0], (int)it.Current.Tag[1], string.Join(",", data.Select(b => b.ToString("X2")))); } break; } } return room; }