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; } } }
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; }
public PuyoFile(bool gvm = false) { Type = gvm ? PuyoArchiveType.GVMFile : PuyoArchiveType.PVMFile; }