Esempio n. 1
0
        public static byte[] Encode(byte[] rgba, G_IM_FMT fmt, G_IM_SIZ siz)
        {
            switch (fmt)
            {
            case G_IM_FMT.G_IM_FMT_RGBA:
                switch (siz)
                {
                case G_IM_SIZ.G_IM_SIZ_16b: return(EncodeRgba16(rgba));

                case G_IM_SIZ.G_IM_SIZ_32b: return(EncodeRgba32(rgba));

                default: throw new N64TextureException("Invalid Size");
                }

            case G_IM_FMT.G_IM_FMT_YUV:
            case G_IM_FMT.G_IM_FMT_CI:
                throw new NotImplementedException();

            /*
             * switch (siz)
             * {
             *  case G_IM_SIZ.G_IM_SIZ_4b: return EncodeCI4(rgba, tlut);
             *  case G_IM_SIZ.G_IM_SIZ_8b: return EncodeCI8(rgba, tlut);
             *  default: throw new N64TextureException("Invalid Size");
             * }
             */
            case G_IM_FMT.G_IM_FMT_IA:
                switch (siz)
                {
                case G_IM_SIZ.G_IM_SIZ_4b: return(EncodeIA4(rgba));

                case G_IM_SIZ.G_IM_SIZ_8b: return(EncodeIA8(rgba));

                case G_IM_SIZ.G_IM_SIZ_16b: return(EncodeIA16(rgba));

                default: throw new N64TextureException("Invalid Size");
                }

            case G_IM_FMT.G_IM_FMT_I:
                switch (siz)
                {
                case G_IM_SIZ.G_IM_SIZ_4b: return(EncodeI4(rgba));

                case G_IM_SIZ.G_IM_SIZ_8b: return(EncodeI8(rgba));

                default: throw new N64TextureException("Invalid Size");
                }

            default:
                throw new N64TextureException("Invalid Format");
            }
        }
Esempio n. 2
0
        public static N64TexFormat ConvertFormat(G_IM_FMT fmt, G_IM_SIZ siz)
        {
            switch (fmt)
            {
            case G_IM_FMT.G_IM_FMT_RGBA:
                switch (siz)
                {
                case G_IM_SIZ.G_IM_SIZ_16b: return(N64TexFormat.RGBA16);

                case G_IM_SIZ.G_IM_SIZ_32b: return(N64TexFormat.RGBA32);

                default: throw new N64TextureException("Invalid Size");
                }

            case G_IM_FMT.G_IM_FMT_YUV:
            case G_IM_FMT.G_IM_FMT_CI:
                switch (siz)
                {
                case G_IM_SIZ.G_IM_SIZ_4b: return(N64TexFormat.CI4);

                case G_IM_SIZ.G_IM_SIZ_8b: return(N64TexFormat.CI8);

                default: throw new N64TextureException("Invalid Size");
                }

            case G_IM_FMT.G_IM_FMT_IA:
                switch (siz)
                {
                case G_IM_SIZ.G_IM_SIZ_4b: return(N64TexFormat.IA4);

                case G_IM_SIZ.G_IM_SIZ_8b: return(N64TexFormat.IA8);

                case G_IM_SIZ.G_IM_SIZ_16b: return(N64TexFormat.IA16);

                default: throw new N64TextureException("Invalid Size");
                }

            case G_IM_FMT.G_IM_FMT_I:
                switch (siz)
                {
                case G_IM_SIZ.G_IM_SIZ_4b: return(N64TexFormat.I4);

                case G_IM_SIZ.G_IM_SIZ_8b: return(N64TexFormat.I8);

                default: throw new N64TextureException("Invalid Size");
                }

            default:
                throw new N64TextureException("Invalid Format");
            }
        }
Esempio n. 3
0
        public static byte[] Decode(int texels, G_IM_FMT fmt, G_IM_SIZ siz, byte[] buff, byte[] tlut)
        {
            switch (fmt)
            {
            case G_IM_FMT.G_IM_FMT_RGBA:
                switch (siz)
                {
                case G_IM_SIZ.G_IM_SIZ_16b: return(DecodeRgba16(texels, buff));

                case G_IM_SIZ.G_IM_SIZ_32b: return(DecodeRgba32(texels, buff));

                default: throw new N64TextureException("Invalid Size");
                }

            case G_IM_FMT.G_IM_FMT_YUV:
            case G_IM_FMT.G_IM_FMT_CI:
                switch (siz)
                {
                case G_IM_SIZ.G_IM_SIZ_4b: return(DecodeCI4(texels, buff, tlut));

                case G_IM_SIZ.G_IM_SIZ_8b: return(DecodeCI8(texels, buff, tlut));

                default: throw new N64TextureException("Invalid Size");
                }

            case G_IM_FMT.G_IM_FMT_IA:
                switch (siz)
                {
                case G_IM_SIZ.G_IM_SIZ_4b: return(DecodeIA4(texels, buff));

                case G_IM_SIZ.G_IM_SIZ_8b: return(DecodeIA8(texels, buff));

                case G_IM_SIZ.G_IM_SIZ_16b: return(DecodeIA16(texels, buff));

                default: throw new N64TextureException("Invalid Size");
                }

            case G_IM_FMT.G_IM_FMT_I:
                switch (siz)
                {
                case G_IM_SIZ.G_IM_SIZ_4b: return(DecodeI4(texels, buff));

                case G_IM_SIZ.G_IM_SIZ_8b: return(DecodeI8(texels, buff));

                default: throw new N64TextureException("Invalid Size");
                }

            default:
                throw new N64TextureException("Invalid Format");
            }
        }
Esempio n. 4
0
        public static unsafe byte[] EncodeBitmap(Bitmap bmp, G_IM_FMT fmt, G_IM_SIZ siz)
        {
            var bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

            byte *argb = (byte *)bmpData.Scan0;

            byte[] rgba = new byte[bmp.Width * bmp.Height * 4];
            for (int i = 0; i < bmp.Width * bmp.Height; i++)
            {
                rgba[4 * i + 0] = argb[4 * i + 2]; //R
                rgba[4 * i + 1] = argb[4 * i + 1]; //G
                rgba[4 * i + 2] = argb[4 * i + 0]; //B
                rgba[4 * i + 3] = argb[4 * i + 3]; //A
            }

            bmp.UnlockBits(bmpData);
            return(Encode(rgba, fmt, siz));
        }
Esempio n. 5
0
        public static unsafe Bitmap DecodeBitmap(int w, int h, G_IM_FMT fmt, G_IM_SIZ siz, byte[] buff, byte[] tlut = null)
        {
            Bitmap bmp     = new Bitmap(w, h);
            var    bmpData = bmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);

            byte *argb = (byte *)bmpData.Scan0;

            byte[] rgba = Decode(w * h, fmt, siz, buff, tlut);
            for (int i = 0; i < w * h; i++)
            {
                argb[4 * i + 3] = rgba[4 * i + 3]; //A
                argb[4 * i + 2] = rgba[4 * i + 0]; //R
                argb[4 * i + 1] = rgba[4 * i + 1]; //G
                argb[4 * i + 0] = rgba[4 * i + 2]; //B
            }

            bmp.UnlockBits(bmpData);
            return(bmp);
        }
Esempio n. 6
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);
        }