Example #1
0
            public override void SetData(byte[] data)
            {
                int validSize = N64Texture.GetTexSize(Width * Height, Format);

                if (data.Length != validSize)
                {
                    throw new Z64ObjectException($"Invalid data size (0x{data.Length:X} instead of 0x{validSize:X})");
                }

                Texture = data;
            }
Example #2
0
        private void UpdateTexture(object sender = null, EventArgs e = null)
        {
            N64TexFormat fmt     = (N64TexFormat)comboBoxTexFmt.SelectedIndex;
            int          w       = (int)valueW.Value;
            int          h       = (int)valueH.Value;
            int          texSize = N64Texture.GetTexSize(w * h, fmt);

            if (!uint.TryParse(textBoxTexAddr.Text, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out uint texAddr))
            {
                return;
            }


            byte[] tlut = null;
            if ((fmt == N64TexFormat.CI4 || fmt == N64TexFormat.CI8) && uint.TryParse(textBoxTlutAddr.Text, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out uint tlutAddr))
            {
                try
                {
                    if (fmt == N64TexFormat.CI4)
                    {
                        tlut = ReadBytes(tlutAddr, 64);
                    }
                    else if (fmt == N64TexFormat.CI8)
                    {
                        tlut = ReadBytes(tlutAddr, 256);
                    }
                }
                catch (Exception)
                {
                    return;
                }
            }

            try
            {
                byte[] tex = ReadBytes(texAddr, texSize);
                textureBox1.Image = N64Texture.DecodeBitmap(w, h, fmt, tex, tlut);
            }
            catch (Exception)
            {
                return;
            }
        }
Example #3
0
        public static List <string> AnalyzeDlists(Z64Object obj, byte[] data, int segmentId)
        {
            List <string> errors = new List <string>();

            List <int> dlists = new List <int>();

            for (int i = 0; i < obj.Entries.Count; i++)
            {
                var entry = obj.Entries[i];
                if (entry.GetEntryType() == Z64Object.EntryType.DList)
                {
                    dlists.Add(obj.OffsetOf(entry));
                }
                else
                {
                    obj.Entries[i] = new Z64Object.UnknowHolder($"unk_{obj.OffsetOf(entry):X8}", entry.GetData());
                }
            }

            foreach (var dlist in dlists)
            {
                uint     lastTexAddr              = 0xFFFFFFFF;
                G_IM_FMT lastFmt                  = (G_IM_FMT)(-1);
                G_IM_SIZ lastSiz                  = (G_IM_SIZ)(-1);
                Z64Object.TextureHolder lastTlut  = null;
                Z64Object.TextureHolder lastCiTex = null;

                bool exit = false;
                for (int i = dlist; i < data.Length && !exit; i += 8)
                {
                    CmdID op = (CmdID)data[i];
                    switch (op)
                    {
                    case CmdID.G_QUAD:
                    case CmdID.G_TRI2:
                    case CmdID.G_TRI1:
                    case CmdID.G_TEXRECTFLIP:
                    case CmdID.G_TEXRECT:
                    {
                        if (lastCiTex != null && lastTlut != null)
                        {
                            lastCiTex.Tlut = lastTlut;
                            lastCiTex      = null;
                        }
                        break;
                    }

                    case CmdID.G_ENDDL:
                    {
                        exit = true;
                        break;
                    }

                    case CmdID.G_MTX:
                    {
                        var gmtx = CmdInfo.DecodeCommand <GMtx>(data, i);
                        var addr = new SegmentedAddress(gmtx.mtxaddr);
                        if (addr.Segmented && addr.SegmentId == segmentId)
                        {
                            obj.AddMtx(1, off: (int)addr.SegmentOff);
                        }
                        break;
                    }

                    case CmdID.G_VTX:
                    {
                        var gvtx = CmdInfo.DecodeCommand <GVtx>(data, i);

                        var addr = new SegmentedAddress(gvtx.vaddr);
                        if (addr.Segmented && addr.SegmentId == segmentId)
                        {
                            try
                            {
                                obj.AddVertices(gvtx.numv, off: (int)addr.SegmentOff);
                            }
                            catch (Exception ex)
                            {
                                errors.Add($"Error in Dlist 0x{new SegmentedAddress(segmentId, dlist).VAddr:X8} : {ex.Message}");
                            }
                        }
                        break;
                    }

                    case CmdID.G_SETTIMG:
                    {
                        var settimg = CmdInfo.DecodeCommand <GSetTImg>(data, i);
                        lastTexAddr = settimg.imgaddr;
                        break;
                    }

                    case CmdID.G_SETTILE:
                    {
                        var settile = CmdInfo.DecodeCommand <GSetTile>(data, i);
                        if (settile.tile != G_TX_TILE.G_TX_LOADTILE)
                        {
                            lastFmt = settile.fmt;
                            lastSiz = settile.siz;
                        }
                        break;
                    }

                    case CmdID.G_SETTILESIZE:
                    {
                        var settilesize = CmdInfo.DecodeCommand <GLoadTile>(data, i);
                        var addr        = new SegmentedAddress(lastTexAddr);

                        if ((int)lastFmt == -1 || (int)lastSiz == -1 || lastTexAddr == 0xFFFFFFFF)
                        {
                            /* can't really thow an exception here since in some object files, there are two gsDPSetTileSize next to each other (see object_en_warp_uzu) */
                            //throw new Z64ObjectAnalyzerException();
                            break;
                        }

                        if (addr.Segmented && addr.SegmentId == segmentId)
                        {
                            try
                            {
                                var tex = obj.AddTexture((int)(settilesize.lrs.Float() + 1), (int)(settilesize.lrt.Float() + 1), N64Texture.ConvertFormat(lastFmt, lastSiz), off: (int)addr.SegmentOff);
                                if (lastFmt == G_IM_FMT.G_IM_FMT_CI)
                                {
                                    lastCiTex = tex;
                                }
                            }
                            catch (Exception ex)
                            {
                                errors.Add($"Error in Dlist 0x{new SegmentedAddress(segmentId, dlist).VAddr:X8} : {ex.Message}");
                            }
                        }

                        lastFmt     = (G_IM_FMT)(-1);
                        lastSiz     = (G_IM_SIZ)(-1);
                        lastTexAddr = 0xFFFFFFFF;

                        break;
                    }

                    case CmdID.G_LOADTLUT:
                    {
                        var loadtlut = CmdInfo.DecodeCommand <GLoadTlut>(data, i);
                        var addr     = new SegmentedAddress(lastTexAddr);

                        if (lastTexAddr == 0xFFFFFFFF)
                        {
                            throw new Z64ObjectAnalyzerException();
                        }

                        int w = GetTlutWidth(loadtlut.count + 1);
                        if (addr.Segmented && addr.SegmentId == segmentId)
                        {
                            try
                            {
                                lastTlut = obj.AddTexture(w, (loadtlut.count + 1) / w, N64Texture.ConvertFormat(G_IM_FMT.G_IM_FMT_RGBA, G_IM_SIZ.G_IM_SIZ_16b), off: (int)addr.SegmentOff);
                            }
                            catch (Exception ex)
                            {
                                errors.Add($"Error in Dlist 0x{new SegmentedAddress(segmentId, dlist).VAddr:X8} : {ex.Message}");
                            }
                        }

                        break;
                    }
                    }
                }
            }

            // These are carried out here as they are dependent on a lot of heuristics.
            // Having lots of the object already mapped out reduces possible mis-identifications.
            FindSkeletons(obj, data, segmentId);
            FindAnimations(obj, data, segmentId);

            obj.GroupUnkEntries();
            obj.FixNames();
            obj.SetData(data);

            return(errors);
        }
Example #4
0
        private static Tuple <List <int>, List <ReservedRegion> > FindRegions(byte[] data, int segmentId, Config cfg)
        {
            List <ReservedRegion> regions = new List <ReservedRegion>();
            List <int>            dlists  = new List <int>();

            var codeEnds = Utils.FindData(data, new byte[] { (byte)CmdID.G_ENDDL, 0, 0, 0, 0, 0, 0, 0, }, 8);

            codeEnds.Insert(0, 0);
            for (int i = 1; i < codeEnds.Count; i++)
            {
                int  end    = codeEnds[i];
                int  texels = -1;
                uint half1  = 0xFFFFFFFF;

                for (int off = end; off >= codeEnds[i - 1] + 8; off -= 8)
                {
                    CmdID op = (CmdID)data[off];

                    if (IsOverlap(off, regions) || !IsOpCodeCorrect(data, off, cfg))
                    {
                        break;
                    }

                    switch (op)
                    {
                    case CmdID.G_RDPHALF_1:
                    {
                        half1 = CmdInfo.DecodeCommand <GRdpHalf>(data, off).word;
                        break;
                    }

                    case CmdID.G_BRANCH_Z:
                    {
                        AddDlist(dlists, segmentId, half1, data.Length);
                        break;
                    }

                    case CmdID.G_DL:
                    {
                        var gdl = CmdInfo.DecodeCommand <GDl>(data, off);
                        AddDlist(dlists, segmentId, gdl.dl, data.Length);
                        break;
                    }

                    case CmdID.G_VTX:
                    {
                        var gmtx = CmdInfo.DecodeCommand <GVtx>(data, off);
                        AddRegion(regions, segmentId, gmtx.vaddr, gmtx.numv * 0x10, data.Length);
                        break;
                    }

                    case CmdID.G_SETTIMG:
                    {
                        var settimg = CmdInfo.DecodeCommand <GSetTImg>(data, off);
                        if (texels == -1)
                        {
                            break;
                        }
                        AddRegion(regions, segmentId, settimg.imgaddr, N64Texture.GetTexSize(texels, settimg.siz), data.Length);
                        texels = -1;
                        break;
                    }

                    case CmdID.G_LOADBLOCK:
                    {
                        var loadblock = CmdInfo.DecodeCommand <GLoadBlock>(data, off);
                        texels = loadblock.texels + 1;
                        break;
                    }

                    case CmdID.G_LOADTLUT:
                    {
                        var loadtlut = CmdInfo.DecodeCommand <GLoadTlut>(data, off);
                        texels = loadtlut.count + 1;
                        break;
                    }

                    default:
                        break;
                    }
                }
            }
            return(new Tuple <List <int>, List <ReservedRegion> >(dlists, regions));
        }
Example #5
0
 public Bitmap GetBitmap()
 {
     return(N64Texture.DecodeBitmap(Width, Height, Format, Texture, Tlut?.Texture));
 }