mirror of
https://github.com/crskycode/GARbro.git
synced 2024-11-27 07:34:00 +08:00
commit
c00f8621da
@ -136,6 +136,8 @@
|
|||||||
<Compile Include="GScripter\ArcDATA.cs" />
|
<Compile Include="GScripter\ArcDATA.cs" />
|
||||||
<Compile Include="Ism\ImagePNG.cs" />
|
<Compile Include="Ism\ImagePNG.cs" />
|
||||||
<Compile Include="Kid\ArcDATRAW.cs" />
|
<Compile Include="Kid\ArcDATRAW.cs" />
|
||||||
|
<Compile Include="Kid\ImageBIP.cs" />
|
||||||
|
<Compile Include="Kid\ImageBIParc.cs" />
|
||||||
<Compile Include="Kid\ImageLBG.cs" />
|
<Compile Include="Kid\ImageLBG.cs" />
|
||||||
<Compile Include="Kid\ImageSPC.cs" />
|
<Compile Include="Kid\ImageSPC.cs" />
|
||||||
<Compile Include="Kogado\ArcARC.cs" />
|
<Compile Include="Kogado\ArcARC.cs" />
|
||||||
@ -179,6 +181,7 @@
|
|||||||
<Compile Include="Macromedia\Palettes.cs" />
|
<Compile Include="Macromedia\Palettes.cs" />
|
||||||
<Compile Include="MAGES\ArcARC20.cs" />
|
<Compile Include="MAGES\ArcARC20.cs" />
|
||||||
<Compile Include="MAGES\ArcFARC.cs" />
|
<Compile Include="MAGES\ArcFARC.cs" />
|
||||||
|
<Compile Include="MAGES\ArcGPDA.cs" />
|
||||||
<Compile Include="MAGES\ArcGTF.cs" />
|
<Compile Include="MAGES\ArcGTF.cs" />
|
||||||
<Compile Include="MAGES\ArcLoveOnce.cs" />
|
<Compile Include="MAGES\ArcLoveOnce.cs" />
|
||||||
<Compile Include="MAGES\ImageBIN.cs" />
|
<Compile Include="MAGES\ImageBIN.cs" />
|
||||||
|
@ -42,12 +42,12 @@ namespace GameRes.Formats.Cri
|
|||||||
|
|
||||||
public SpcOpener ()
|
public SpcOpener ()
|
||||||
{
|
{
|
||||||
Extensions = new string[] { "spc" };
|
Extensions = new string[] { "spc", "bip" };
|
||||||
}
|
}
|
||||||
|
|
||||||
public override ArcFile TryOpen (ArcView file)
|
public override ArcFile TryOpen (ArcView file)
|
||||||
{
|
{
|
||||||
if (!file.Name.HasExtension (".spc"))
|
if (!file.Name.HasExtension (".spc") && !file.Name.HasExtension(".bip"))
|
||||||
return null;
|
return null;
|
||||||
uint unpacked_size = file.View.ReadUInt32 (0);
|
uint unpacked_size = file.View.ReadUInt32 (0);
|
||||||
if (unpacked_size <= 0x20 || unpacked_size > 0x5000000)
|
if (unpacked_size <= 0x20 || unpacked_size > 0x5000000)
|
||||||
|
@ -103,6 +103,9 @@ namespace GameRes.Formats.Ivory
|
|||||||
bool IsValidInput (Stream input, uint width, uint height, int pixel_size)
|
bool IsValidInput (Stream input, uint width, uint height, int pixel_size)
|
||||||
{
|
{
|
||||||
int total = (int)width * (int)height;
|
int total = (int)width * (int)height;
|
||||||
|
// Other formats will be incorrectly recognized as this format, try to correct it.
|
||||||
|
if (total * pixel_size < input.Length / 10)
|
||||||
|
return false;
|
||||||
int dst = 0;
|
int dst = 0;
|
||||||
while (dst < total)
|
while (dst < total)
|
||||||
{
|
{
|
||||||
|
@ -38,6 +38,8 @@ namespace GameRes.Formats.Kid
|
|||||||
entry.Size = size;
|
entry.Size = size;
|
||||||
dir.Add(entry);
|
dir.Add(entry);
|
||||||
}
|
}
|
||||||
|
if (dir.Count == 0)
|
||||||
|
return null;
|
||||||
return new ArcFile(file, this, dir);
|
return new ArcFile(file, this, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
207
ArcFormats/Kid/ImageBIP.cs
Normal file
207
ArcFormats/Kid/ImageBIP.cs
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.Composition;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Media3D;
|
||||||
|
|
||||||
|
namespace GameRes.Formats.Kid
|
||||||
|
{
|
||||||
|
public class BipFormat : ImageFormat
|
||||||
|
{
|
||||||
|
public override string Tag { get { return "BIP/PS2"; } }
|
||||||
|
public override string Description { get { return "PS2 tiled bitmap format"; } }
|
||||||
|
public override uint Signature { get { return 0; } } //0x05000000
|
||||||
|
|
||||||
|
public override ImageMetaData ReadMetaData(IBinaryStream file)
|
||||||
|
{
|
||||||
|
uint header = file.ReadUInt32();
|
||||||
|
uint real_sign;
|
||||||
|
bool multi = false; // not implemented
|
||||||
|
if (header < 5)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else if (header == 5)
|
||||||
|
{
|
||||||
|
real_sign = 0x14;
|
||||||
|
}
|
||||||
|
else if (header >= 6 && header <= 0x0C)
|
||||||
|
{
|
||||||
|
real_sign = header * 4;
|
||||||
|
multi = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null; // throw new NotSupportedException(string.Format("BIP Chara format not supported."));
|
||||||
|
}
|
||||||
|
|
||||||
|
file.Seek(0x10, SeekOrigin.Begin);
|
||||||
|
uint fstart = file.ReadUInt16(); // usually 0x100
|
||||||
|
|
||||||
|
// Non-Sequential read
|
||||||
|
file.Seek(0x88, SeekOrigin.Begin); // next one +20
|
||||||
|
uint width = file.ReadUInt16();
|
||||||
|
uint height = file.ReadUInt16();
|
||||||
|
if (width > 2560 || height > 1440 || width < 16 || height < 16) // suppose not so large or so small
|
||||||
|
return null;
|
||||||
|
|
||||||
|
file.Seek(real_sign, SeekOrigin.Begin); // usually 0x14
|
||||||
|
if ((file.ReadUInt16() & 0x7FFF) != fstart)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
uint sign = file.ReadUInt16();
|
||||||
|
uint dy;
|
||||||
|
bool sliced = true;
|
||||||
|
long denominator = file.Length;
|
||||||
|
if (multi)
|
||||||
|
{
|
||||||
|
file.Seek(0xA2, SeekOrigin.Begin);
|
||||||
|
uint f2start = file.ReadUInt16();
|
||||||
|
denominator = f2start * 1024 + fstart + 0x100;
|
||||||
|
}
|
||||||
|
double oversize = (double)width * height * 4 / denominator;
|
||||||
|
|
||||||
|
file.Seek(0x90, SeekOrigin.Begin);
|
||||||
|
//uint size = file.ReadUInt32(); // not size
|
||||||
|
uint sizesign = file.ReadUInt16();
|
||||||
|
uint sizesign_high = file.ReadUInt16();
|
||||||
|
//size &= 0x00FFFFFF;
|
||||||
|
//if (sign == 0x13 && size != (file.Length - 0x100) || sign == 0x17 && size != (file.Length - 0x100)* 2)
|
||||||
|
if (sizesign != 0 || sizesign_high == 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
uint pixelsize = (sizesign_high & 0x00FF) * 0x10000; /*r16: 2*pixelsize r32: pixelsize*/
|
||||||
|
|
||||||
|
if (oversize > 0.87 /*sign == 0x13*/)
|
||||||
|
{
|
||||||
|
// no-sliced oversize min: 0.87178 max: 0.9866
|
||||||
|
// sliced oversize max: 0.8333 min: 0.76
|
||||||
|
dy = 16;
|
||||||
|
sliced = false;
|
||||||
|
// sign = focusT / 2
|
||||||
|
}
|
||||||
|
else if (sign > 0x50)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else if (((double)pixelsize / denominator) <= 1.045 && sign != 0x2E && sign != 0x33)
|
||||||
|
{
|
||||||
|
/*known oversize 1.02 for expected <=1, noticed smallest r16 oversize 1.045+ for MOAR2 EV_SP04A, 0.99+ for MOAR1 OM2_TT13A, 0.89+ for MOAR3 C3_30A*/
|
||||||
|
//sign % 2 == 0 && sign <= 0x2A && sign != 0x22 && sign != 0x1A
|
||||||
|
//sign == 0x16 || sign == 0x20 || sign == 0x2A
|
||||||
|
dy = 32;
|
||||||
|
// sign = focusT * 2
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//sign == 0x17 || sign == 0x19 || sign == 0x1F || sign == 0x25 || sign == 0x2E || sign == 0x34
|
||||||
|
dy = 16;
|
||||||
|
// sign = focusT / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
// uint dx = dy * 32;
|
||||||
|
|
||||||
|
return new BipImageMetaData
|
||||||
|
{
|
||||||
|
Width = width,
|
||||||
|
Height = height,
|
||||||
|
BlockSize = dy,
|
||||||
|
Sliced = sliced,
|
||||||
|
Multi = multi,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public override ImageData Read(IBinaryStream file, ImageMetaData info)
|
||||||
|
{
|
||||||
|
if (info == null)
|
||||||
|
throw new NotSupportedException(string.Format("Not BIP texture format."));
|
||||||
|
var bipheader = (BipImageMetaData)info;
|
||||||
|
file.Seek(0x10, SeekOrigin.Begin);
|
||||||
|
uint fstart = file.ReadUInt16(); // usually 0x100
|
||||||
|
file.Seek(fstart, SeekOrigin.Begin);
|
||||||
|
byte[] pixels = new byte[bipheader.iWidth * bipheader.iHeight * 4];
|
||||||
|
uint dy = bipheader.BlockSize;
|
||||||
|
uint dx = dy * 32;
|
||||||
|
if (bipheader.Sliced)
|
||||||
|
{
|
||||||
|
long dwidth = ((bipheader.iWidth + (dy - 2) - 1) / (dy - 2)) * dy;
|
||||||
|
long dheight = ((bipheader.iHeight + (dy - 2) - 1) / (dy - 2)) * dy;
|
||||||
|
long focus_H = (dwidth* dheight + dx - 1) / dx;
|
||||||
|
long focus_T = (focus_H + dy - 1) / dy;
|
||||||
|
|
||||||
|
for (int t = 0; t < focus_T; t++)
|
||||||
|
{
|
||||||
|
for(int y = 0; y < dy; y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < dx; x++)
|
||||||
|
{
|
||||||
|
var pixel = file.ReadBytes(4); //RGBA with wrong A
|
||||||
|
long i2x = x + t * dx;
|
||||||
|
long i3t = i2x / dwidth;
|
||||||
|
long i3x = i2x - i3t * dwidth;
|
||||||
|
long i3y = i3t * (dy - 2) + y;
|
||||||
|
long i4x = i3x - i3x / dy * dy + i3x / dy * (dy - 2);
|
||||||
|
if (i3x >= dwidth || i4x >= bipheader.iWidth || i3y >= bipheader.iHeight)
|
||||||
|
continue;
|
||||||
|
long target = (i4x + i3y * bipheader.iWidth) * 4;
|
||||||
|
//BGRA
|
||||||
|
pixels[target] = pixel[2];
|
||||||
|
pixels[target + 1] = pixel[1];
|
||||||
|
pixels[target + 2] = pixel[0];
|
||||||
|
if (pixel[3] >= byte.MaxValue / 2)
|
||||||
|
pixels[target + 3] = byte.MaxValue;
|
||||||
|
else
|
||||||
|
pixels[target + 3] = (byte)(pixel[3] << 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
long focus_H = (bipheader.iWidth * bipheader.iHeight + dx - 1) / dx;
|
||||||
|
long focus_T = (focus_H + dy - 1) / dy;
|
||||||
|
for (int t = 0; t < focus_T; t++)
|
||||||
|
{
|
||||||
|
for (int y = 0; y < dy; y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < dx; x++)
|
||||||
|
{
|
||||||
|
var pixel = file.ReadBytes(4); //RGBA with wrong A
|
||||||
|
long i2x = x + t * dx;
|
||||||
|
long i3t = i2x / bipheader.iWidth;
|
||||||
|
long i3x = i2x - i3t * bipheader.iWidth;
|
||||||
|
long i3y = i3t * dy + y;
|
||||||
|
if (i3x >= bipheader.iWidth || i3y >= bipheader.iHeight)
|
||||||
|
continue;
|
||||||
|
long target = (i3x + i3y * bipheader.iWidth) * 4;
|
||||||
|
//BGRA
|
||||||
|
pixels[target] = pixel[2];
|
||||||
|
pixels[target + 1] = pixel[1];
|
||||||
|
pixels[target + 2] = pixel[0];
|
||||||
|
if (pixel[3] >= byte.MaxValue / 2)
|
||||||
|
pixels[target + 3] = byte.MaxValue;
|
||||||
|
else
|
||||||
|
pixels[target + 3] = (byte)(pixel[3] << 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ImageData.Create(info, PixelFormats.Bgra32, null, pixels); ;
|
||||||
|
}
|
||||||
|
public override void Write(Stream file, ImageData image)
|
||||||
|
{
|
||||||
|
throw new System.NotImplementedException("BipFormat.Write not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
class BipImageMetaData : ImageMetaData
|
||||||
|
{
|
||||||
|
public uint BlockSize { get; set; }
|
||||||
|
public bool Sliced { get; set; }
|
||||||
|
public bool Multi { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
44
ArcFormats/Kid/ImageBIParc.cs
Normal file
44
ArcFormats/Kid/ImageBIParc.cs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
using GameRes.Compression;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.Composition;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace GameRes.Formats.Kid
|
||||||
|
{
|
||||||
|
[Export(typeof(ImageFormat))]
|
||||||
|
public class BipArkFormat: BipFormat
|
||||||
|
{
|
||||||
|
public override string Tag { get { return "BIP/PS2 compressed"; } }
|
||||||
|
public override string Description { get { return "PS2 tiled bitmap format with lzss compress"; } }
|
||||||
|
public override uint Signature { get { return 0; } }
|
||||||
|
public BipArkFormat()
|
||||||
|
{
|
||||||
|
Extensions = new string[] { "bip" };
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ImageMetaData ReadMetaData(IBinaryStream stream)
|
||||||
|
{
|
||||||
|
uint unpacked_size = stream.Signature;
|
||||||
|
if (unpacked_size <= 0x20 || unpacked_size > 0x5000000) // ~83MB
|
||||||
|
return null;
|
||||||
|
stream.Position = 4;
|
||||||
|
using (var lzss = new LzssStream(stream.AsStream, LzssMode.Decompress, true))
|
||||||
|
using (var input = new SeekableStream(lzss))
|
||||||
|
using (var bip = new BinaryStream(input, stream.Name))
|
||||||
|
return base.ReadMetaData(bip);
|
||||||
|
}
|
||||||
|
public override ImageData Read(IBinaryStream stream, ImageMetaData info)
|
||||||
|
{
|
||||||
|
stream.Position = 4;
|
||||||
|
using (var lzss = new LzssStream(stream.AsStream, LzssMode.Decompress, true))
|
||||||
|
using (var input = new SeekableStream(lzss))
|
||||||
|
using (var bip = new BinaryStream(input, stream.Name))
|
||||||
|
return base.Read(bip, info);
|
||||||
|
}
|
||||||
|
public override void Write(Stream file, ImageData image)
|
||||||
|
{
|
||||||
|
throw new System.NotImplementedException("BipFormat.Write not implemented");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
49
ArcFormats/MAGES/ArcGPDA.cs
Normal file
49
ArcFormats/MAGES/ArcGPDA.cs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.Composition;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace GameRes.Formats.MAGES
|
||||||
|
{
|
||||||
|
[Export(typeof(ArchiveFormat))]
|
||||||
|
public class GpdaOpener : ArchiveFormat
|
||||||
|
{
|
||||||
|
public override string Tag { get { return "DAT/GPDA"; } }
|
||||||
|
public override string Description { get { return "PCSG00543 resource archive"; } }
|
||||||
|
public override uint Signature { get { return 0x41445047; } } // 'GPDA'
|
||||||
|
public override bool IsHierarchic { get { return false; } }
|
||||||
|
public override bool CanWrite { get { return false; } }
|
||||||
|
|
||||||
|
public override ArcFile TryOpen(ArcView file)
|
||||||
|
{
|
||||||
|
int count = file.View.ReadInt32(0x0C);
|
||||||
|
if (!IsSaneCount(count))
|
||||||
|
return null;
|
||||||
|
var dir = new List<Entry>(count);
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
uint filename_offset = file.View.ReadUInt32(16 * i + 16 + 12);
|
||||||
|
uint filename_length = file.View.ReadUInt32(filename_offset) - 1;
|
||||||
|
string name = file.View.ReadString(filename_offset + 4, filename_length);
|
||||||
|
/*byte c;
|
||||||
|
List<byte> namebyte = new List<byte>();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
c = file.View.ReadByte((long)index_offset);
|
||||||
|
if (c == 0 | index_offset > filename_end) break;
|
||||||
|
namebyte.Add(c);
|
||||||
|
index_offset++;
|
||||||
|
}*/
|
||||||
|
//var sjis = System.Text.Encoding.GetEncoding("Shift-JIS");
|
||||||
|
//var name = Encoding.ASCII.GetString(namebyte.ToArray());
|
||||||
|
var entry = Create<Entry>(name);
|
||||||
|
|
||||||
|
entry.Offset = file.View.ReadUInt32(16 * i + 16);
|
||||||
|
entry.Size = file.View.ReadUInt32(16 * i + 16 + 8);
|
||||||
|
if (!entry.CheckPlacement(file.MaxOffset))
|
||||||
|
return null;
|
||||||
|
dir.Add(entry);
|
||||||
|
}
|
||||||
|
return new ArcFile(file, this, dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user