diff --git a/ArcFormats/ArcFormats.csproj b/ArcFormats/ArcFormats.csproj
index df8b82df..e4c4bf52 100644
--- a/ArcFormats/ArcFormats.csproj
+++ b/ArcFormats/ArcFormats.csproj
@@ -132,6 +132,8 @@
+
+
diff --git a/ArcFormats/Kid/ImageBIP.cs b/ArcFormats/Kid/ImageBIP.cs
new file mode 100644
index 00000000..6f641cf2
--- /dev/null
+++ b/ArcFormats/Kid/ImageBIP.cs
@@ -0,0 +1,164 @@
+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();
+ if (header == 9)
+ {
+ throw new NotSupportedException(string.Format("BIP Chara format not supported."));
+ }
+ else if (header != 5)
+ {
+ return null;
+ }
+
+ file.Seek(0x14, SeekOrigin.Begin);
+ if (file.ReadUInt16() != 256)
+ {
+ return null;
+ }
+ uint sign = file.ReadUInt16();
+ uint dy = 0;
+ bool sliced = true;
+ if (sign == 0x17)
+ {
+ dy = 16;
+ }
+ else if (sign == 0x16)
+ {
+ dy = 16;
+ sliced = false;
+ }
+ else if (sign == 0x13)
+ {
+ dy = 32;
+ }
+ else
+ {
+ return null;
+ }
+
+ //uint dx = dy * 32;
+ file.Seek(0x88, SeekOrigin.Begin);
+ uint width = file.ReadUInt16();
+ uint height = file.ReadUInt16();
+ if (width >= 1280 || height >= 1280) // suppose not so large
+ return null;
+
+ file.Seek(0x90, SeekOrigin.Begin);
+ uint size = file.ReadUInt32();
+ size &= 0x00FFFFFF;
+ if (sign == 0x13 && size != (file.Length - 0x100) || sign == 0x17 && size != (file.Length - 0x100)* 2)
+ {
+ return null;
+ }
+ return new BipImageMetaData
+ {
+ Width = width,
+ Height = height,
+ BlockSize = dy,
+ Sliced = sliced,
+ };
+ }
+ 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(0x100, 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; }
+ }
+ }
+}
diff --git a/ArcFormats/Kid/ImageBIParc.cs b/ArcFormats/Kid/ImageBIParc.cs
new file mode 100644
index 00000000..8a7cafa4
--- /dev/null
+++ b/ArcFormats/Kid/ImageBIParc.cs
@@ -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");
+ }
+ }
+}