예제 #1
0
        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);
        }
    }
예제 #2
0
        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);
        }
예제 #3
0
        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;
        }