mirror of
https://github.com/crskycode/GARbro.git
synced 2024-11-27 07:34:00 +08:00
implemented 16bpp LIM images.
This commit is contained in:
parent
dee61a2929
commit
37da6b588e
@ -479,10 +479,12 @@ namespace GameRes.Formats.Liar
|
||||
int flag = stream.ReadByte() & 0xF;
|
||||
if (flag != 2 && flag != 3)
|
||||
return null;
|
||||
stream.Seek (5, SeekOrigin.Current);
|
||||
stream.ReadByte();
|
||||
using (var file = new ArcView.Reader (stream))
|
||||
{
|
||||
var meta = new ImageMetaData { BPP = 32 };
|
||||
int bpp = 0x10 == file.ReadUInt16() ? 16 : 32;
|
||||
var meta = new ImageMetaData { BPP = bpp };
|
||||
file.ReadUInt16();
|
||||
meta.Width = file.ReadUInt32();
|
||||
meta.Height = file.ReadUInt32();
|
||||
return meta;
|
||||
@ -512,16 +514,24 @@ namespace GameRes.Formats.Liar
|
||||
byte[] m_image;
|
||||
int m_width;
|
||||
int m_height;
|
||||
int m_bpp;
|
||||
|
||||
public byte[] Data { get { return m_image; } }
|
||||
public PixelFormat Format { get { return PixelFormats.Bgra32; } }
|
||||
public PixelFormat Format { get; private set; }
|
||||
|
||||
public Reader (Stream file, ImageMetaData info)
|
||||
{
|
||||
m_input = new ArcView.Reader (file);
|
||||
m_width = (int)info.Width;
|
||||
m_height = (int)info.Height;
|
||||
m_image = new byte[m_width*m_height*4];
|
||||
m_bpp = info.BPP;
|
||||
if (32 == m_bpp)
|
||||
Format = PixelFormats.Bgra32;
|
||||
else if (16 == m_bpp)
|
||||
Format = PixelFormats.Bgr565;
|
||||
else
|
||||
throw new InvalidFormatException();
|
||||
m_image = new byte[m_width*m_height*m_bpp/8];
|
||||
}
|
||||
|
||||
int m_remaining;
|
||||
@ -529,25 +539,19 @@ namespace GameRes.Formats.Liar
|
||||
int m_bits;
|
||||
|
||||
public void Unpack ()
|
||||
{
|
||||
if (32 == m_bpp)
|
||||
Unpack32bpp();
|
||||
else
|
||||
Unpack16bpp();
|
||||
}
|
||||
|
||||
void Unpack32bpp ()
|
||||
{
|
||||
byte mask = 0xFF;
|
||||
for (int i = 3; i >= 0; --i)
|
||||
{
|
||||
int channel_size = m_input.ReadInt32();
|
||||
if (null == m_output)
|
||||
m_output = new byte[channel_size];
|
||||
else if (channel_size != m_output.Length)
|
||||
throw new InvalidFormatException();
|
||||
|
||||
m_remaining = m_input.ReadInt32();
|
||||
int index_size = m_input.ReadUInt16();
|
||||
if (null == m_index || index_size > m_index.Length)
|
||||
m_index = new byte[index_size];
|
||||
m_input.ReadInt16(); // ignored
|
||||
if (m_index.Length != m_input.Read (m_index, 0, m_index.Length))
|
||||
throw new InvalidFormatException ("Unexpected end of file");
|
||||
|
||||
UnpackChannel();
|
||||
UnpackChannel (3);
|
||||
int src = 0;
|
||||
for (int p = i; p < m_image.Length; p += 4)
|
||||
{
|
||||
@ -557,13 +561,117 @@ namespace GameRes.Formats.Liar
|
||||
}
|
||||
}
|
||||
|
||||
void UnpackChannel ()
|
||||
void Unpack16bpp ()
|
||||
{
|
||||
int image_size = m_input.ReadInt32();
|
||||
m_output = m_image;
|
||||
|
||||
m_remaining = m_input.ReadInt32();
|
||||
int index_size = m_input.ReadUInt16() * 2;
|
||||
if (null == m_index || index_size > m_index.Length)
|
||||
m_index = new byte[index_size];
|
||||
m_input.ReadInt16(); // ignored
|
||||
if (index_size != m_input.Read (m_index, 0, index_size))
|
||||
throw new InvalidFormatException ("Unexpected end of file");
|
||||
|
||||
int card;
|
||||
if (index_size > 8192)
|
||||
{
|
||||
m_index_threshold = 14;
|
||||
m_index_length_limit = 16;
|
||||
card = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_index_threshold = 6;
|
||||
m_index_length_limit = 12;
|
||||
card = 3;
|
||||
}
|
||||
m_current = 0;
|
||||
int dst = 0;
|
||||
while (dst < m_output.Length)
|
||||
{
|
||||
int bits = GetBits (3);
|
||||
int bits = GetBits (card);
|
||||
if (-1 == bits)
|
||||
break;
|
||||
|
||||
if (0 != bits)
|
||||
{
|
||||
int index = GetIndex (bits);
|
||||
if (index < 0)
|
||||
break;
|
||||
if (dst + 1 >= m_output.Length)
|
||||
break;
|
||||
|
||||
m_output[dst++] = m_index[index*2];
|
||||
m_output[dst++] = m_index[index*2+1];
|
||||
}
|
||||
else
|
||||
{
|
||||
int count = GetBits (4);
|
||||
if (-1 == count)
|
||||
break;
|
||||
|
||||
bits = GetBits (card);
|
||||
if (-1 == bits)
|
||||
break;
|
||||
|
||||
int index = GetIndex (bits);
|
||||
if (-1 == index)
|
||||
break;
|
||||
count += 2;
|
||||
index *= 2;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (dst + 1 >= m_output.Length)
|
||||
return;
|
||||
m_output[dst++] = m_index[index];
|
||||
m_output[dst++] = m_index[index+1];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_input.BaseStream.Position < m_input.BaseStream.Length)
|
||||
{
|
||||
m_output = null;
|
||||
UnpackChannel (3);
|
||||
var pixels = new byte[m_width*m_height*4];
|
||||
int alpha_src = 0;
|
||||
dst = 0;
|
||||
for (int i = 0; i < m_image.Length; i += 2)
|
||||
{
|
||||
int color = LittleEndian.ToUInt16 (m_image, i);
|
||||
pixels[dst++] = (byte)((color & 0x001F) * 0xFF / 0x1F);
|
||||
pixels[dst++] = (byte)((color & 0x07E0) * 0xFF / 0x7E0);
|
||||
pixels[dst++] = (byte)((color & 0xF800) * 0xFF / 0xF800);
|
||||
pixels[dst++] = (byte)~m_output[alpha_src++];
|
||||
}
|
||||
m_image = pixels;
|
||||
Format = PixelFormats.Bgra32;
|
||||
}
|
||||
}
|
||||
|
||||
void UnpackChannel (int card)
|
||||
{
|
||||
m_index_threshold = 6;
|
||||
m_index_length_limit = 12;
|
||||
|
||||
int channel_size = m_input.ReadInt32();
|
||||
if (null == m_output || m_output.Length < channel_size)
|
||||
m_output = new byte[channel_size];
|
||||
m_remaining = m_input.ReadInt32();
|
||||
|
||||
int index_size = m_input.ReadUInt16();
|
||||
if (null == m_index || index_size > m_index.Length)
|
||||
m_index = new byte[index_size];
|
||||
m_input.ReadInt16(); // ignored
|
||||
if (index_size != m_input.Read (m_index, 0, index_size))
|
||||
throw new InvalidFormatException ("Unexpected end of file");
|
||||
|
||||
m_current = 0;
|
||||
int dst = 0;
|
||||
while (dst < m_output.Length)
|
||||
{
|
||||
int bits = GetBits (card);
|
||||
if (-1 == bits)
|
||||
break;
|
||||
|
||||
@ -583,7 +691,7 @@ namespace GameRes.Formats.Liar
|
||||
if (-1 == count)
|
||||
break;
|
||||
|
||||
bits = GetBits (3);
|
||||
bits = GetBits (card);
|
||||
if (-1 == bits)
|
||||
break;
|
||||
|
||||
@ -608,7 +716,10 @@ namespace GameRes.Formats.Liar
|
||||
{
|
||||
if (0 == m_current)
|
||||
{
|
||||
if (0 == m_remaining)
|
||||
return 0;
|
||||
m_bits = m_input.ReadByte();
|
||||
--m_remaining;
|
||||
m_current = 8;
|
||||
}
|
||||
v <<= 1;
|
||||
@ -620,9 +731,12 @@ namespace GameRes.Formats.Liar
|
||||
return v;
|
||||
}
|
||||
|
||||
int m_index_threshold;
|
||||
int m_index_length_limit;
|
||||
|
||||
private int GetIndex (int bits)
|
||||
{
|
||||
if (bits < 7)
|
||||
if (bits <= m_index_threshold)
|
||||
{
|
||||
if (0 == bits)
|
||||
return -1;
|
||||
@ -630,7 +744,7 @@ namespace GameRes.Formats.Liar
|
||||
return GetBits (1);
|
||||
return (1 << bits) | GetBits (bits);
|
||||
}
|
||||
for (int i = 6; i < 12; ++i)
|
||||
for (int i = m_index_threshold; i < m_index_length_limit; ++i)
|
||||
{
|
||||
bits = GetBits (1);
|
||||
if (-1 == bits)
|
||||
|
@ -187,14 +187,16 @@ Yume Miru Kusuri<br/>
|
||||
</td></tr>
|
||||
<tr><td>*.wip<br/>*.msk<br/>*.mos</td><td><tt>WIPF</tt></td><td>No</td></tr>
|
||||
<tr><td>*.pna</td><td><tt>PNAP</tt></td><td>No</td></tr>
|
||||
<tr class="odd"><td>*.xfl</td><td><tt>LB</tt></td><td>Yes</td><td rowspan="3">Liar-soft</td><td rowspan="3">
|
||||
<tr class="odd"><td>*.xfl</td><td><tt>LB</tt></td><td>Yes</td><td rowspan="4">Liar-soft</td><td rowspan="4">
|
||||
Angel Bullet<br/>
|
||||
Fairytale Requiem<br/>
|
||||
Love Negotiator<br/>
|
||||
Sekien no Inganock<br/>
|
||||
Shikkoku no Sharnoth<br/>
|
||||
</td></tr>
|
||||
<tr class="odd"><td>*.lwg</td><td><tt>LG</tt></td><td>No</td></tr>
|
||||
<tr class="odd"><td>*.wcg</td><td><tt>WGq</tt></td><td>Yes</td></tr>
|
||||
<tr class="odd"><td>*.lim</td><td><tt>LM</tt></td><td>No</td></tr>
|
||||
<tr><td>*.xp3</td><td><tt>XP3</tt></td><td>Yes</td><td rowspan="2">KiriKiri</td><td rowspan="2">
|
||||
Altered Pink ~Tokumu Sentai Duel Ranger~<br/>
|
||||
Aozora Gakko no Sensei-kun<br/>
|
||||
@ -221,6 +223,7 @@ Nuki Doki!<br/>
|
||||
Okiba ga Nai!<br/>
|
||||
Oku-sama wa Moto Yariman<br/>
|
||||
Ore no Saimin Fantasia<br/>
|
||||
RGH ~Koi to Hero to Gakuen to~<br/>
|
||||
Riding Incubus<br/>
|
||||
Seirei Tenshou<br/>
|
||||
Se-kirara<br/>
|
||||
@ -330,6 +333,7 @@ Jokyoushi wo Kurau<br/>
|
||||
Lovers Collection<br/>
|
||||
Nachtmusik<br/>
|
||||
Nachtmusik Another<br/>
|
||||
Oto☆Puri<br/>
|
||||
Samayou Mitama ni Yasuragi no Toki wo<br/>
|
||||
Time Trouble ~Marie ni Kubikkake~<br/>
|
||||
</td></tr>
|
||||
@ -431,6 +435,7 @@ Hissatsu Chikannin II<br/>
|
||||
Ryoujoku Gojuusou<br/>
|
||||
Tokumei Sentai Sirenger<br/>
|
||||
Tokumei Sentai Yuzu Ranger<br/>
|
||||
Zetsuboushi<br/>
|
||||
</td></tr>
|
||||
<tr class="odd"><td>*.cwp</td><td><tt>CWDP</tt></td><td>Yes</td></tr>
|
||||
<tr class="odd"><td>*.cwd</td><td><tt>cwd</tt></td><td>No</td></tr>
|
||||
@ -468,6 +473,7 @@ Dies irae ~Amantes amentes~<br/>
|
||||
Kajiri Kamui Kagura<br/>
|
||||
Paradise Lost<br/>
|
||||
Sakashiki Hito ni Miru Kokoro<br/>
|
||||
Tenmon Dokei no Aria<br/>
|
||||
Zettai Meikyuu Grimm<br/>
|
||||
</td></tr>
|
||||
<tr class="odd"><td>*.mgf</td><td><tt>MalieGF</tt></td><td>Yes</td></tr>
|
||||
@ -536,7 +542,9 @@ Yami no Koe Zero<br/>
|
||||
<tr><td>*.vaw<br/>*.wgq</td><td><tt>IF PACKTYPE==</tt><br/><tt>OGG</tt></td><td>No</td></tr>
|
||||
<tr class="odd"><td>*.aos</td><td>-</td><td>No</td><td rowspan="2">LiLiM</td><td rowspan="2">
|
||||
Answer Dead<br/>
|
||||
Houou Senki Maimu<br/>
|
||||
Kango Sentai Nurse Ranger<br/>
|
||||
Megami Taisen<br/>
|
||||
</td></tr>
|
||||
<tr class="odd"><td>*.abm</td><td><tt>BM</tt></td><td>No</td></tr>
|
||||
<tr><td>*.arc<br/>*.xarc<br/>*.bin</td><td><tt>MIKO</tt><br/><tt>KOTORI</tt><br/><tt>XARC</tt></td><td>No</td><td rowspan="2">Xuse<br/>ETERNAL</td><td rowspan="2">
|
||||
@ -549,6 +557,7 @@ Seinarukana -The Spirit of Eternity Sword 2-<br/>
|
||||
<tr><td>*.wag<br/>*.4ag<br/>*.004</td><td><tt>WAG@</tt><br/><tt>GAF4</tt></td><td>No</td></tr>
|
||||
<tr class="odd"><td>*.ykc</td><td><tt>YKC001</tt></td><td>Yes</td><td rowspan="2">Yuka</td><td rowspan="2">
|
||||
Aozora no Mieru Oka<br/>
|
||||
HoneyComing<br/>
|
||||
PriministAr<br/>
|
||||
SuGirly Wish<br/>
|
||||
_summer<br/>
|
||||
@ -708,7 +717,7 @@ Level Justice<br/>
|
||||
</td></tr>
|
||||
<tr><td>*.iph</td><td><tt>RIFF....IPH fmt</tt></td><td>No</td></tr>
|
||||
<tr><td>*.aog</td><td><tt>AoiOgg</tt></td><td>No</td></tr>
|
||||
<tr><td>*.box</td><td><tt>AOIBX10</tt></td><td>No</td></tr>
|
||||
<tr><td>*.box</td><td><tt>AOIBX10</tt><br/><tt>AOIBOX7</tt></td><td>No</td></tr>
|
||||
<tr class="odd"><td>*.gd+*.dll</td><td>-</td><td>No</td><td>Xuse</td><td>
|
||||
Eien no Aselia -The Spirit of Eternity Sword-
|
||||
</td></tr>
|
||||
@ -757,6 +766,7 @@ Angenehm Platz -Kleiner Garten Sie Erstellen-<br/>
|
||||
</td></tr>
|
||||
<tr><td>*.eme</td><td><tt>RREDATA</tt></td><td>No</td><td>Emon Engine</td><td>
|
||||
Ase Nure Shoujo Misaki "Anata no Nioi de Icchau!"<br/>
|
||||
Hitomi no Rakuin ~Inbaku no Mesu Dorei~<br/>
|
||||
</td></tr>
|
||||
<tr class="odd"><td>*.grp</td><td>-</td><td>No</td><td>Ankh</td><td>
|
||||
Mozu<br/>
|
||||
|
Loading…
Reference in New Issue
Block a user