Esempio n. 1
0
        public void Decode()
        {
            byte[] bytes    = AlphabetMapper.TranslateMetroidStringToComputerBytes(Encoded);
            byte   checksum = bytes[ChecksumByte - 1];
            byte   shift    = bytes[ShiftByte - 1];

            byte[] decoded = new byte[ChecksumByteCount];
            Buffer.BlockCopy(bytes, 0, decoded, 0, ChecksumByteCount);

            decoded = decoded.RotateLeft(shift);

            byte verifyChecksum = CalculateChecksum(decoded, shift);

            if (verifyChecksum != checksum)
            {
                throw new ChecksumException("Invalid Metroid password");
            }

            // The bitpacking we use assumes that information is packed from the left which means that it makes a big difference for a byte full of bools
            // Information is actually packed from the right of the byte
            // Ergo we just have to flip each byte
            // However first we handle the only 32-bit value (which can't be fixed by a naive flip)
            if (!BitConverter.IsLittleEndian)
            {
                // The game age value comes in little-endian format
                Swap(decoded, GameAgeStartByteIndex, GameAgeEndByteIndex);
                Swap(decoded, GameAgeStartByteIndex + 1, GameAgeEndByteIndex - 1);
            }
            for (int i = 0; i < decoded.Length; i++)
            {
                if (i >= GameAgeStartByteIndex && i <= GameAgeEndByteIndex)
                {
                    continue;
                }
                decoded[i] = decoded[i].ReverseBits();
            }

            var reader     = new PackedBitReader(decoded);
            var serializer = new PackedBitSerializer(typeof(PasswordProperties));

            Properties = serializer.Deserialize(reader) as PasswordProperties;

            Properties.Checksum = checksum;
            Properties.Shift    = shift;
        }
Esempio n. 2
0
        public void Encode()
        {
            var writer     = new PackedBitWriter();
            var serializer = new PackedBitSerializer(typeof(PasswordProperties));

            serializer.Serialize(writer, Properties);

            byte[] bytes = writer.ToArray();

            // The bitpacking we use assumes that information is packed from the left which means that it makes a big difference for a byte full of bools
            // Information is actually packed from the right of the byte
            // Ergo we just have to flip each byte
            // However first we handle the only 32-bit value (which can't be fixed by a naive flip)
            if (!BitConverter.IsLittleEndian)
            {
                // The game age value comes in little-endian format
                Swap(bytes, GameAgeStartByteIndex, GameAgeEndByteIndex);
                Swap(bytes, GameAgeStartByteIndex + 1, GameAgeEndByteIndex - 1);
            }
            for (int i = 0; i < ChecksumByteCount; i++)
            {
                if (i >= GameAgeStartByteIndex && i <= GameAgeEndByteIndex)
                {
                    continue;
                }
                bytes[i] = bytes[i].ReverseBits();
            }

            byte checksum = CalculateChecksum(bytes, Properties.Shift);

            Properties.Checksum = checksum;

            if (Properties.Shift > 0)
            {
                bytes = bytes.RotateRight(Properties.Shift);
            }

            byte[] encoded = new byte[ChecksumByte];
            Buffer.BlockCopy(bytes, 0, encoded, 0, ChecksumByteCount);
            encoded[ShiftByte - 1]    = Properties.Shift;
            encoded[ChecksumByte - 1] = Properties.Checksum;

            Encoded = AlphabetMapper.TranslateComputerBytesToMetroidString(encoded);
        }