Exemple #1
0
        public Puyo(byte[] pvmdata)
        {
            ArchiveBase puyobase;

            Entries = new List <ArchiveEntry>();

            Type = Identify(pvmdata);
            switch (Type)
            {
            case PuyoArchiveType.PVMFile:
                puyobase = new PvmArchive();
                break;

            case PuyoArchiveType.GVMFile:
                puyobase = new GvmArchive();
                break;

            default:
                throw new Exception("Error: Unknown archive format");
            }

            ArchiveReader archiveReader = puyobase.Open(pvmdata);

            foreach (var puyoentry in archiveReader.Entries)
            {
                MemoryStream vrstream = (MemoryStream)(puyoentry.Open());
                switch (Type)
                {
                case PuyoArchiveType.PVMFile:
                    PvrTexture pvrt = new PvrTexture(vrstream);
                    if (pvrt.NeedsExternalPalette)
                    {
                        PaletteRequired = true;
                    }
                    Entries.Add(new PVMEntry(vrstream.ToArray(), Path.GetFileName(puyoentry.Name)));
                    break;

                case PuyoArchiveType.GVMFile:
                    GvrTexture gvrt = new GvrTexture(vrstream);
                    if (gvrt.NeedsExternalPalette)
                    {
                        PaletteRequired = true;
                    }
                    Entries.Add(new GVMEntry(vrstream.ToArray(), Path.GetFileName(puyoentry.Name)));
                    break;
                }
            }
        }
Exemple #2
0
        public PuyoFile(byte[] pvmdata)
        {
            bool bigendianbk = ByteConverter.BigEndian;

            Entries = new List <GenericArchiveEntry>();
            Type    = Identify(pvmdata);
            switch (Type)
            {
            case PuyoArchiveType.PVMFile:
                ByteConverter.BigEndian = false;
                break;

            case PuyoArchiveType.GVMFile:
                ByteConverter.BigEndian = true;
                break;

            default:
                throw new Exception("Error: Unknown archive format");
            }

            // Get PVM/GVM flags and calculate item size in the entry table
            ushort numtextures  = ByteConverter.ToUInt16(pvmdata, 0x0A);
            int    pvmentrysize = 2;
            int    gbixoffset   = 0;
            int    nameoffset   = 0;

            PuyoArchiveFlags flags = (PuyoArchiveFlags)ByteConverter.ToUInt16(pvmdata, 0x08);

            if (flags.HasFlag(PuyoArchiveFlags.Filenames))
            {
                nameoffset = pvmentrysize;
            }
            pvmentrysize += 28;
            if (flags.HasFlag(PuyoArchiveFlags.PixelDataFormat))
            {
                pvmentrysize += 2;
            }
            if (flags.HasFlag(PuyoArchiveFlags.TextureDimensions))
            {
                pvmentrysize += 2;
            }
            if (flags.HasFlag(PuyoArchiveFlags.GlobalIndex))
            {
                gbixoffset = pvmentrysize;
            }
            pvmentrysize += 4;

            int offsetfirst = BitConverter.ToInt32(pvmdata, 0x4) + 8; // Always Little Endian
            int textureaddr = GetPVRTOffset(pvmdata, offsetfirst);    // Where texture data begins

            for (int t = 0; t < numtextures; t++)
            {
                int    size_gbix = flags.HasFlag(PuyoArchiveFlags.GlobalIndex) ? 16 : 0;
                int    size      = BitConverter.ToInt32(pvmdata, textureaddr + 4); // Always Little Endian
                byte[] pvrchunk  = new byte[size + 8 + size_gbix];

                // Handle cases when data size in the PVR/GVR header goes beyond the range of the archive (Billy Hatcher)
                if ((textureaddr + size + 8) > pvmdata.Length)
                {
                    do
                    {
                        size--;
                    }while ((textureaddr + size + 8) > pvmdata.Length);
                }

                Array.Copy(pvmdata, textureaddr, pvrchunk, 0 + size_gbix, size + 8);
                // Add GBIX header if the PVM/GVM has GBIX enabled
                if (flags.HasFlag(PuyoArchiveFlags.GlobalIndex))
                {
                    Array.Copy(BitConverter.GetBytes(Magic_GBIX), 0, pvrchunk, 0, 4); // Little Endian
                    pvrchunk[4] = 0x08;                                               // Always 8 according to PuyoTools
                    uint   gbix  = BitConverter.ToUInt32(pvmdata, 0xC + pvmentrysize * t + gbixoffset);
                    byte[] gbixb = BitConverter.GetBytes(gbix);
                    Array.Copy(gbixb, 0, pvrchunk, 8, 4);
                }

                // Set filename if the PVM/GVM has filenames
                string entryfn = t.ToString("D3");
                if (flags.HasFlag(PuyoArchiveFlags.Filenames))
                {
                    byte[] namestring = new byte[28];
                    for (int n = 0; n < 28; n++)
                    {
                        // Entry names in some PVMs (e.g. DEMO.PVM in Dream Passport 3) have garbage data after the first 0, so it needs to be truncated
                        byte ndt = pvmdata[0xC + pvmentrysize * t + nameoffset + n];
                        if (ndt == 0)
                        {
                            break;
                        }
                        namestring[n] = ndt;
                    }
                    entryfn = Encoding.ASCII.GetString(namestring).TrimEnd((char)0);
                }
                else
                {
                    hasNameData = false;
                }

                if (t < numtextures - 1)  // Get the address of the next PVRT chunk, unless it's the last one
                {
                    textureaddr = GetPVRTOffset(pvmdata, textureaddr + size + 8);
                }

                // Add PVR/GVR texture to the entry list
                if (Type == PuyoArchiveType.PVMFile)
                {
                    PvrTexture pvrt = new PvrTexture(pvrchunk);
                    if (pvrt.NeedsExternalPalette)
                    {
                        PaletteRequired = true;
                    }
                    Entries.Add(new PVMEntry(pvrchunk, entryfn + ".pvr"));
                }
                else
                {
                    GvrTexture gvrt = new GvrTexture(pvrchunk);
                    if (gvrt.NeedsExternalPalette)
                    {
                        PaletteRequired = true;
                    }
                    Entries.Add(new GVMEntry(pvrchunk, entryfn + ".gvr"));
                }
            }
            ByteConverter.BigEndian = bigendianbk;
        }
Exemple #3
0
 public PuyoFile(bool gvm = false)
 {
     Type = gvm ? PuyoArchiveType.GVMFile : PuyoArchiveType.PVMFile;
 }