Пример #1
0
        private void DWordInterleaveWrap_(
            byte[] src,
            uint srcIdx,
            uint srcMask,
            uint numQWords)
        {
            uint p0;
            int  idx0, idx1;

            while (numQWords-- > 0)
            {
                idx0 = (int)(srcIdx++ & srcMask);
                idx1 = (int)(srcIdx++ & srcMask);

                // TODO: Original logic was meant for u32, so we need to think in terms
                // of ints.

                var offset0 = 4 * idx0;
                var offset1 = 4 * idx1;

                p0 = IoUtil.ReadUInt32(src, (uint)offset0);
                var p1 = IoUtil.ReadUInt32(src, (uint)offset1);

                IoUtil.WriteInt32(src, p1, ref offset0);
                IoUtil.WriteInt32(src, p0, ref offset1);
            }
        }
Пример #2
0
        /// <summary>
        ///   Shamelessly copied from GLideN64's source.
        /// </summary>
        private void LoadTile32b_(
            ref TileDescriptor tileDescriptor,
            TimgArgs timgArgs)
        {
            var uls = tileDescriptor.ULS;
            var ult = tileDescriptor.ULT;
            var lrs = tileDescriptor.LRS;
            var lrt = tileDescriptor.LRT;

            var width  = lrs - uls + 1;
            var height = lrt - ult + 1;

            var line  = tileDescriptor.LineSize << 2;
            var tbase = tileDescriptor.TmemOffset << 2;

            IoUtil.SplitAddress(timgArgs.Address, out var bank, out var offset);

            var targetBank = Asserts.Assert(RamBanks.GetBankByIndex(bank));

            var timgWidth = timgArgs.Width;

            for (var j = 0; j < height; ++j)
            {
                var tline  = tbase + line * j;
                var s      = ((j + ult) * timgWidth) + uls;
                var xorval = (j & 1) != 0 ? 3 : 1;

                for (var i = 0; i < width; ++i)
                {
                    var addr = offset + s + i;
                    var c    = IoUtil.ReadUInt32(targetBank, (uint)(4 * addr));

                    var ptr = ((tline + i) ^ xorval) & 0x3ff;

                    var offset1 = 2 * ptr;
                    IoUtil.WriteInt16(targetBank, ref offset1, (ushort)(c >> 16));

                    var offset2 = 2 * (ptr | 0x400);
                    IoUtil.WriteInt16(targetBank, ref offset2, (ushort)(c & 0xffff));
                }
            }
        }
Пример #3
0
        /// <summary>
        ///   Parses a set of animations according to the spec at:
        ///   https://wiki.cloudmodding.com/oot/Animation_Format#Normal_Animations
        /// </summary>
        // TODO: Some jank still slips through, is there a proper list of these
        // addresses somewhere in the file?
        public IList <IAnimation>?GetCommonAnimations(
            IBank bank,
            int limbCount,
            ListBox animationList)
        {
            animationList.Items.Clear();

            uint trackCount = (uint)(limbCount * 3);
            var  animations = new List <IAnimation>();

            // Guesstimating the index by looking for an spot where the header's angle
            // address and track address have the same bank as the param at the top.
            for (var i = 4; i < bank.Count - 12; i += 4)
            {
                var attemptOffset = (uint)(i - 4);

                // Verifies the frame count is positive.
                var frameCount = IoUtil.ReadUInt16(bank, attemptOffset);
                if (frameCount == 0)
                {
                    continue;
                }

                var rotationValuesAddress = IoUtil.ReadUInt32(
                    bank,
                    attemptOffset + 4);
                IoUtil.SplitAddress(rotationValuesAddress,
                                    out var rotationValuesBank,
                                    out var rotationValuesOffset);

                // Verifies the rotation values address has a valid bank.
                if (!RamBanks.IsValidBank(rotationValuesBank))
                {
                    continue;
                }

                // Verifies the rotation indices address has a valid bank.
                var rotationIndicesAddress = IoUtil.ReadUInt32(
                    bank,
                    attemptOffset + 8);
                IoUtil.SplitAddress(rotationIndicesAddress,
                                    out var rotationIndicesBank,
                                    out var rotationIndicesOffset);
                if (!RamBanks.IsValidBank(rotationIndicesBank))
                {
                    continue;
                }

                // Obtains the specified banks.
                var rotationValuesBuffer =
                    Asserts.Assert(RamBanks.GetBankByIndex(rotationValuesBank));
                var rotationIndicesBuffer =
                    Asserts.Assert(RamBanks.GetBankByIndex(rotationIndicesBank));

                // Offsets should be within bounds of the bank.
                var validRotationValuesOffset =
                    rotationValuesOffset < rotationValuesBuffer.Count;
                var validRotationIndicesOffset =
                    rotationIndicesOffset < rotationIndicesBuffer.Count;

                if (!validRotationValuesOffset || !validRotationIndicesOffset)
                {
                    continue;
                }

                // Angle count should be greater than 0.
                var angleCount =
                    (uint)((rotationIndicesOffset - rotationValuesOffset) / 2L);
                var validAngleCount = rotationIndicesOffset > rotationValuesOffset &&
                                      angleCount > 0L;
                if (!validAngleCount)
                {
                    continue;
                }

                // Should have zeroes present in two spots of the animation header.
                var hasZeroes =
                    IoUtil.ReadUInt16(bank, attemptOffset + 2) == 0 &&
                    IoUtil.ReadUInt16(bank, attemptOffset + 14) == 0;
                if (!hasZeroes)
                {
                    continue;
                }

                // All values of "tTrack" should be within the bounds of .Angles.
                var validTTracks = true;
                var limit        = IoUtil.ReadUInt16(bank, attemptOffset + 12);
                for (var i1 = 0; i1 < 3 + trackCount; i1++)
                {
                    var tTrack = IoUtil.ReadUInt16(
                        rotationIndicesBuffer,
                        (uint)(rotationIndicesOffset + 2 * i1));
                    if (tTrack < limit)
                    {
                        if (tTrack >= angleCount)
                        {
                            validTTracks = false;
                            goto badTTracks;
                        }
                    }
                    else if ((uint)(tTrack + frameCount) > angleCount)
                    {
                        validTTracks = false;
                        goto badTTracks;
                    }
                }

badTTracks:
                if (!validTTracks)
                {
                    continue;
                }

                var animation = new NormalAnimation {
                    FrameCount  = frameCount,
                    TrackOffset = rotationIndicesOffset,
                    AngleCount  = angleCount
                };

                animation.Angles = new ushort[animation.AngleCount];
                for (var i1 = 0; i1 < animation.AngleCount; ++i1)
                {
                    animation.Angles[i1] =
                        IoUtil.ReadUInt16(rotationValuesBuffer,
                                          rotationValuesOffset);
                    rotationValuesOffset = (uint)(rotationValuesOffset + 2L);
                }

                // Translation is at the start.
                var xList =
                    ReadFrames_(
                        IoUtil.ReadUInt16(rotationIndicesBuffer,
                                          animation.TrackOffset + 0),
                        limit,
                        animation);
                var yList =
                    ReadFrames_(
                        IoUtil.ReadUInt16(rotationIndicesBuffer,
                                          animation.TrackOffset + 2),
                        limit,
                        animation);
                var zList =
                    ReadFrames_(
                        IoUtil.ReadUInt16(rotationIndicesBuffer,
                                          animation.TrackOffset + 4),
                        limit,
                        animation);

                animation.Positions = new Vec3s[animation.FrameCount];
                for (var pi = 0; pi < animation.FrameCount; ++pi)
                {
                    animation.Positions[pi] = new Vec3s {
                        X = (short)xList[Math.Min(pi, xList.Length - 1)],
                        Y = (short)yList[Math.Min(pi, yList.Length - 1)],
                        Z = (short)zList[Math.Min(pi, zList.Length - 1)],
                    };
                }

                animation.Tracks = new NormalAnimationTrack[trackCount];

                var tTrackOffset = (int)(animation.TrackOffset + 6L);
                for (var i1 = 0; i1 < trackCount; ++i1)
                {
                    var track = animation.Tracks[i1] = new NormalAnimationTrack();

                    var tTrack =
                        IoUtil.ReadUInt16(rotationIndicesBuffer,
                                          (uint)tTrackOffset);
                    if (tTrack < limit)
                    {
                        // Constant (single value)
                        track.Type      = 0;
                        track.Frames    = new ushort[1];
                        track.Frames[0] = animation.Angles[tTrack];
                    }
                    else
                    {
                        // Keyframes
                        track.Type   = 1;
                        track.Frames = new ushort[animation.FrameCount];
                        for (var i2 = 0; i2 < animation.FrameCount; ++i2)
                        {
                            try {
                                track.Frames[i2] = animation.Angles[tTrack + i2];
                            } catch {
                                return(null);
                            }
                        }
                    }

                    tTrackOffset += 2;
                }

                animations.Add(animation);

                animationList.Items.Add("0x" + Conversion.Hex(i));
            }

            return(animations.Count > 0 ? animations : null);
        }
Пример #4
0
        /// <summary>
        ///   Parses a set of animations according to the spec at:
        ///   https://wiki.cloudmodding.com/oot/Animation_Format#C_code
        /// </summary>
        public IList <IAnimation>?GetLinkAnimations(
            IBank HeaderData,
            int LimbCount,
            IBank animationData,
            ListBox animationList)
        {
            animationList.Items.Clear();
            var animations = new List <IAnimation>();

            var trackCount = (uint)(LimbCount * 3);
            var frameSize  = 2 * (3 + trackCount) + 2;

            for (uint i = 0x2310; i <= 0x34F8; i += 4)
            {
                // Verifies the frame count is positive.
                var frameCount = IoUtil.ReadUInt16(HeaderData, i);
                if (frameCount == 0)
                {
                    continue;
                }

                var animationAddress = IoUtil.ReadUInt32(HeaderData, i + 4);
                IoUtil.SplitAddress(animationAddress,
                                    out var animationBank,
                                    out var animationOffset);

                // Should use link_animetion bank.
                var validAnimationBank = animationBank == 7;
                if (!validAnimationBank)
                {
                    continue;
                }

                // Should have zeroes in the expected bytes of the header.
                var hasZeroes = IoUtil.ReadUInt16(HeaderData, i + 2) == 0;
                if (!hasZeroes)
                {
                    continue;
                }

                // Should be within the bounds of the bank.
                var validOffset = animationOffset + frameSize * frameCount <
                                  animationData.Count;
                if (!validOffset)
                {
                    continue;
                }

                // Everything looks good with this animation location!

                // Starts parsing animation from this spot.
                var tracks       = new LinkAnimetionTrack[(int)(trackCount - 1L + 1)];
                var positions    = new Vec3s[frameCount];
                var facialStates = new FacialState[frameCount];

                for (int t = 0, loopTo = (int)(trackCount - 1L);
                     t <= loopTo;
                     t++)
                {
                    tracks[t] = new LinkAnimetionTrack(1, new ushort[frameCount]);
                }

                for (int f = 0, loopTo1 = frameCount - 1; f <= loopTo1; f++)
                {
                    var frameOffset = (uint)(animationOffset + f * frameSize);

                    // TODO: This should be ReadInt16() instead.
                    positions[f] = new Vec3s {
                        X = (short)IoUtil.ReadUInt16(animationData, frameOffset),
                        Y = (short)IoUtil.ReadUInt16(animationData, frameOffset + 2),
                        Z = (short)IoUtil.ReadUInt16(animationData, frameOffset + 4),
                    };
                    for (int t = 0, loopTo2 = (int)(trackCount - 1L);
                         t <= loopTo2;
                         t++)
                    {
                        var trackOffset = (uint)(frameOffset + 2 * (3 + t));
                        tracks[t].Frames[f] = IoUtil.ReadUInt16(animationData, trackOffset);
                    }

                    var facialStateOffset =
                        (int)(frameOffset + 2 * (3 + trackCount));
                    var facialState = animationData[facialStateOffset + 1];
                    var mouthState  = IoUtil.ShiftR(facialState, 4, 4);
                    var eyeState    = IoUtil.ShiftR(facialState, 0, 4);

                    facialStates[f] = new FacialState((EyeState)eyeState,
                                                      (MouthState)mouthState);
                }

                var animation =
                    new LinkAnimetion(frameCount, tracks, positions, facialStates);
                animations.Add(animation);

                animationList.Items.Add("0x" + Conversion.Hex(i));
            }

            return(animations.Count > 0 ? animations : null);
        }
Пример #5
0
 public void Update(IList <byte> src, uint offset)
 => this.Update(IoUtil.ReadUInt32(src, offset),
                IoUtil.ReadUInt32(src, offset + 4));