예제 #1
0
        private uint ParseCreditRecord(INTV.Core.Utility.BinaryReader reader, uint runningTotal)
        {
            // The format of the Credits block consists of:
            // 1 byte bit-field describing which credits apply to the subsequent name
            // EITHER a 1-byte shorthand for the name (0x80-0xFF), or, a NULL-terminated UTF-8 string for the name.
            var bytesParsed = 0u;
            var creditFlags = (CreditFlags)reader.ReadByte();

            ++bytesParsed;
            ++runningTotal;

            var name      = string.Empty;
            var character = reader.ReadByte();

            ++bytesParsed;
            ++runningTotal;

            if (!Authors.TryGetValue(character, out name))
            {
                // Discard the "stuffing" byte that indicates  UTF-8 or 0x01 should follow.
                if (character == 0x01)
                {
                    character = reader.ReadByte();
                    ++bytesParsed;
                    ++runningTotal;
                }

                var nameBuffer = new List <byte>();
                nameBuffer.Add(character);

                while ((character != 0) && (runningTotal < Length))
                {
                    character = reader.ReadByte();
                    nameBuffer.Add(character);
                    ++bytesParsed;
                    ++runningTotal;
                }

                name = System.Text.Encoding.UTF8.GetString(nameBuffer.ToArray(), 0, nameBuffer.Count).Trim('\0');
            }

            for (int i = 0; i < NumberOfCreditFlags; ++i)
            {
                var credit = (CreditFlags)(1 << i);
                if (creditFlags.HasFlag(credit))
                {
                    AddCredit(credit, name);
                }
            }
            return(bytesParsed);
        }
예제 #2
0
        /// <summary>
        /// Creates a new instance of a LuigiDataBlock by inflating it from a BinaryReader.
        /// </summary>
        /// <param name="reader">The binary reader containing the data to deserialize to create the object.</param>
        /// <returns>A new instance of a LuigiDataBlock.</returns>
        /// <remarks>It is assumed that the reader is currently positioned at the beginning of a serialized LUIGI data block.</remarks>
        public static LuigiDataBlock Inflate(INTV.Core.Utility.BinaryReader reader)
        {
            LuigiDataBlock dataBlock = null;
            var            blockType = (LuigiDataBlockType)reader.ReadByte();

            switch (blockType)
            {
            case LuigiDataBlockType.SetScrambleKey:
                dataBlock = new LuigiScrambleKeyBlock();
                break;

            case LuigiDataBlockType.MemoryMapAndPermissionsTable:
                dataBlock = new LuigiMemoryMapAndPermissionsTableBlock();
                break;

            case LuigiDataBlockType.DataHunk:
                dataBlock = new LuigiDataHunkBlock();
                break;

            case LuigiDataBlockType.Metadata:
                dataBlock = new LuigiMetadataBlock();
                break;

            case LuigiDataBlockType.EndOfFile:
                dataBlock = new LuigiEndOfFileBlock();
                break;

            default:
                dataBlock = new LuigiDataBlock((LuigiDataBlockType)blockType);
                break;
            }
            dataBlock._deserializeByteCount  = BlockTypeSize;
            dataBlock._deserializeByteCount += dataBlock.Deserialize(reader);
            return(dataBlock);
        }
예제 #3
0
        /// <summary>
        /// Parses a date / time value from ROM metadata.
        /// </summary>
        /// <param name="reader">A binary reader to use to get the data.</param>
        /// <param name="payloadLength">Payload length of the metadata to parse, in bytes.</param>
        /// <returns>A MetadataDateTime that contains the date and time parsed from metadata, as well as flags indicating date and time field validity and specifics.</returns>
        public static MetadataDateTime ParseDateTimeFromMetadata(this INTV.Core.Utility.BinaryReader reader, uint payloadLength)
        {
            var remainingPayload = (int)payloadLength;
            var dateTimeFlags    = MetadataDateTimeFlags.None;

            var year = MetadataDateTime.DefaultYear;

            if (remainingPayload > 0)
            {
                dateTimeFlags |= MetadataDateTimeFlags.Year;
                year           = 1900 + reader.ReadByte();
                --remainingPayload;
            }

            var month = MetadataDateTime.DefaultMonth;

            if (remainingPayload > 0)
            {
                month = reader.ReadByte();
                --remainingPayload;
                var monthRange = new Range <int>(1, 12);
                if (!monthRange.IsValueInRange(month))
                {
                    month = MetadataDateTime.DefaultMonth;
                }
                else
                {
                    dateTimeFlags |= MetadataDateTimeFlags.Month;
                }
            }

            var day = MetadataDateTime.DefaultDay;

            if (remainingPayload > 0)
            {
                day = reader.ReadByte();
                --remainingPayload;
                var dayRange = new Range <int>(1, DateTime.DaysInMonth(year, month));
                if (!dateTimeFlags.HasFlag(MetadataDateTimeFlags.Month) || !dayRange.IsValueInRange(day))
                {
                    day = MetadataDateTime.DefaultDay;
                }
                else
                {
                    dateTimeFlags |= MetadataDateTimeFlags.Day;
                }
            }

            var hour = MetadataDateTime.DefaultHour;

            if (remainingPayload > 0)
            {
                hour = reader.ReadByte();
                --remainingPayload;
                var hourRange = new Range <int>(0, 23);
                if (!dateTimeFlags.HasFlag(MetadataDateTimeFlags.Day) || !hourRange.IsValueInRange(hour))
                {
                    hour = MetadataDateTime.DefaultHour;
                }
                else
                {
                    dateTimeFlags |= MetadataDateTimeFlags.Hour;
                }
            }

            var minute = MetadataDateTime.DefaultMinute;

            if (remainingPayload > 0)
            {
                minute = reader.ReadByte();
                --remainingPayload;
                var minuteRange = new Range <int>(0, 59);
                if (!dateTimeFlags.HasFlag(MetadataDateTimeFlags.Hour) || !minuteRange.IsValueInRange(minute))
                {
                    minute = MetadataDateTime.DefaultMinute;
                }
                else
                {
                    dateTimeFlags |= MetadataDateTimeFlags.Minute;
                }
            }

            var second = MetadataDateTime.DefaultSecond;

            if (remainingPayload > 0)
            {
                second = reader.ReadByte();
                --remainingPayload;
                if (dateTimeFlags.HasFlag(MetadataDateTimeFlags.Minute) && (second == 60))
                {
                    dateTimeFlags |= MetadataDateTimeFlags.LeapSecond | MetadataDateTimeFlags.Second;
                    second         = 59;
                }
                else if (!dateTimeFlags.HasFlag(MetadataDateTimeFlags.Minute) || (second > 59))
                {
                    second = MetadataDateTime.DefaultSecond;
                }
                else
                {
                    dateTimeFlags |= MetadataDateTimeFlags.Second;
                }
            }

            var utcOffsetHours = MetadataDateTime.DefaultUtcOffsetHours;

            if (remainingPayload > 0)
            {
                utcOffsetHours = reader.ReadSByte();
                --remainingPayload;
                var offsetHoursRange = new Range <int>(-12, 12);
                if (!dateTimeFlags.HasFlag(MetadataDateTimeFlags.Second) || !offsetHoursRange.IsValueInRange(utcOffsetHours))
                {
                    utcOffsetHours = MetadataDateTime.DefaultUtcOffsetHours;
                }
                else
                {
                    dateTimeFlags |= MetadataDateTimeFlags.UtcOffset;
                }
            }

            var utcOffsetMinutes = MetadataDateTime.DefaultUtcOffsetMinutes;

            if (remainingPayload > 0)
            {
                utcOffsetMinutes = reader.ReadByte();
                --remainingPayload;
                if (!dateTimeFlags.HasFlag(MetadataDateTimeFlags.UtcOffset) || (utcOffsetMinutes > 59))
                {
                    utcOffsetMinutes = MetadataDateTime.DefaultUtcOffsetMinutes;
                }
                else
                {
                    dateTimeFlags |= MetadataDateTimeFlags.UtcOffset;
                }
            }

            if (remainingPayload > 0)
            {
                System.Diagnostics.Debug.WriteLine("Too many bytes left! Draining...");
                reader.BaseStream.Seek(remainingPayload, System.IO.SeekOrigin.Current);
            }

            var date = DateTimeOffset.MinValue;

            if (dateTimeFlags != MetadataDateTimeFlags.None)
            {
                var offset = dateTimeFlags.HasFlag(MetadataDateTimeFlags.UtcOffset) ? new TimeSpan(utcOffsetHours, utcOffsetMinutes, 0) : TimeSpan.Zero;
                date = new DateTimeOffset(year, month, day, hour, minute, second, offset);
            }

            return(new MetadataDateTime(date, dateTimeFlags));
        }