Merge pull request #77 from Manicsteiner/private_build

Multiple changes of TIM2/KLZ
This commit is contained in:
Crsky
2025-01-22 16:40:16 +08:00
committed by GitHub
15 changed files with 691 additions and 14 deletions

View File

@@ -131,7 +131,9 @@
<Compile Include="Artemis\ImageNekoPNG.cs" />
<Compile Include="CsWare\AudioWAV.cs" />
<Compile Include="CsWare\ImageGDT.cs" />
<Compile Include="DigitalWorks\ArcPACsingle.cs" />
<Compile Include="DigitalWorks\ArcPACPS2.cs" />
<Compile Include="DigitalWorks\ImageTM2arc.cs" />
<Compile Include="DxLib\HuffmanDecoder.cs" />
<Compile Include="DxLib\WidgetDXA.xaml.cs">
<DependentUpon>WidgetDXA.xaml</DependentUpon>
@@ -142,8 +144,10 @@
<Compile Include="GScripter\ArcDATA.cs" />
<Compile Include="Ism\ImagePNG.cs" />
<Compile Include="Kid\ArcDATRAW.cs" />
<Compile Include="Kid\ArcKLZ.cs" />
<Compile Include="Kid\ImageBIP.cs" />
<Compile Include="Kid\ImageBIParc.cs" />
<Compile Include="Kid\ImageKLZ.cs" />
<Compile Include="Kid\ImageLBG.cs" />
<Compile Include="Kid\ImageSPC.cs" />
<Compile Include="Kogado\ArcARC.cs" />

View File

@@ -0,0 +1,88 @@
//! \file ArcPACPS2.cs
//! \date 2018 Sep 18
//! \brief Digital Works PS2 resource archive.
//
// Copyright (C) 2018 by morkt
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using GameRes.Compression;
namespace GameRes.Formats.DigitalWorks
{
[Export(typeof(ArchiveFormat))]
public class PacSingleOpener : ArchiveFormat
{
public override string Tag { get { return "PAC/LZS-TIM2"; } }
public override string Description { get { return "LZS-TIM2 Image archive"; } }
public override uint Signature { get { return 0x535A4C; } } // 'LZS'
public override bool IsHierarchic { get { return false; } }
public override bool CanWrite { get { return false; } }
/**
Target games:
Cafe Little Wish SLPM-65294
F Fanatic SLPM-65296
*/
public override ArcFile TryOpen (ArcView file)
{
if (!file.View.AsciiEqual(9, "TIM2"))
return null;
var dir = new List<Entry> (1);
var entry = FormatCatalog.Instance.Create<PackedEntry> (file.Name);
entry.Offset = 0L;
entry.Size = (uint)file.MaxOffset;
if (!entry.CheckPlacement (file.MaxOffset))
return null;
dir.Add (entry);
return new ArcFile (file, this, dir);
}
public override Stream OpenEntry (ArcFile arc, Entry entry)
{
var pent = entry as PackedEntry;
if (null == pent)
return base.OpenEntry (arc, entry);
if (!pent.IsPacked)
{
if (!arc.File.View.AsciiEqual (entry.Offset, "LZS\0"))
return base.OpenEntry (arc, entry);
pent.IsPacked = true;
pent.UnpackedSize = arc.File.View.ReadUInt32 (entry.Offset+4);
}
var input = arc.File.CreateStream (entry.Offset+8, entry.Size-8);
bool embedded_lzs = (input.Signature & ~0xF0u) == 0x535A4C0F; // 'LZS'
var lzs = new LzssStream (input);
if (embedded_lzs)
{
var header = new byte[8];
lzs.Read (header, 0, 8);
pent.UnpackedSize = header.ToUInt32 (4);
lzs = new LzssStream (lzs);
}
return lzs;
}
}
}

View File

@@ -23,6 +23,7 @@
// IN THE SOFTWARE.
//
using GameRes.Formats.Strings;
using System;
using System.ComponentModel.Composition;
using System.IO;
@@ -36,6 +37,7 @@ namespace GameRes.Formats.DigitalWorks
public int PaletteSize;
public int HeaderSize;
public int Colors;
public byte Alpha;
}
[Export(typeof(ImageFormat))]
@@ -48,8 +50,16 @@ namespace GameRes.Formats.DigitalWorks
public Tim2Format ()
{
Extensions = new string[] { "tm2", "ext" };
Settings = new[] { AlphaFormat };
}
FixedSetSetting AlphaFormat = new FixedSetSetting(Properties.Settings.Default)
{
Name = "TIM2AlphaFormat",
Text = arcStrings.Tim2AlphaFormat,
ValuesSet = new[] { "No Alpha", "RGBX", "RGBA" },
};
public override ImageMetaData ReadMetaData (IBinaryStream file)
{
var header = file.ReadHeader (0x40);
@@ -59,9 +69,18 @@ namespace GameRes.Formats.DigitalWorks
case 1: bpp = 16; break;
case 2: bpp = 24; break;
case 3: bpp = 32; break;
case 4: bpp = 4; break; //16color
case 5: bpp = 8; break;
default: return null;
}
byte alpha;
switch (AlphaFormat.Get<String>())
{
case "No Alpha": alpha = 0; break;
case "RGBX": alpha = 7; break;
case "RGBA":
default: alpha = 8; break;
}
return new Tim2MetaData {
Width = header.ToUInt16 (0x24),
Height = header.ToUInt16 (0x26),
@@ -69,6 +88,7 @@ namespace GameRes.Formats.DigitalWorks
PaletteSize = header.ToInt32 (0x14),
HeaderSize = header.ToUInt16 (0x1C),
Colors = header.ToUInt16 (0x1E),
Alpha = alpha, //header.ToUInt16(0x30) == 0?// not so sure, there will be omissions
};
}
@@ -99,39 +119,69 @@ namespace GameRes.Formats.DigitalWorks
m_info = info;
switch (info.BPP)
{
case 8: Format = PixelFormats.Indexed8; break;
case 16: Format = PixelFormats.Bgr555; break;
case 24: Format = PixelFormats.Bgr24; break;
case 32: Format = PixelFormats.Bgra32; break;
case 4: Format = PixelFormats.Indexed4; break;
case 8: Format = PixelFormats.Indexed8; break;
case 16: Format = PixelFormats.Bgr555; break;
case 24: Format = PixelFormats.Bgr24; break;
case 32: Format = PixelFormats.Bgra32; break;
}
}
public byte[] Unpack ()
{
m_input.Position = 0x10 + m_info.HeaderSize;
int pixel_size = m_info.BPP / 8;
int image_size = (int)m_info.Width * (int)m_info.Height * pixel_size;
double pixel_size = (double)m_info.BPP / 8;
int image_size = (int)((int)m_info.Width * (int)m_info.Height * pixel_size);
var output = m_input.ReadBytes (image_size);
if (pixel_size <= 8 && m_info.Colors > 0)
Palette = ReadPalette (m_info.Colors);
Palette = ReadPalette (m_info.Colors, m_info.Alpha);
if (pixel_size >= 3)
if (pixel_size == 3 || pixel_size == 4 && m_info.Alpha == 8)
{
for (int i = 0; i < image_size; i += pixel_size)
for (int i = 0; i < image_size; i += (int)pixel_size)
{
byte r = output[i];
output[i] = output[i+2];
output[i+2] = r;
}
}
if (pixel_size == 4 && m_info.Alpha == 7)
{
for (int i = 0; i < image_size; i += 4)
{
byte r = output[i];
output[i] = output[i + 2];
output[i + 2] = r;
if (output[i + 3] >= byte.MaxValue / 2)
output[i + 3] = byte.MaxValue;
else
output[i + 3] = (byte)(output[i + 3] << 1);
}
}
if (pixel_size == 4 && m_info.Alpha == 0)
{
for (int i = 0; i < image_size; i += 4)
{
byte r = output[i];
output[i] = output[i + 2];
output[i + 2] = r;
output[i + 3] = byte.MaxValue;
}
}
return output;
}
BitmapPalette ReadPalette (int color_num)
BitmapPalette ReadPalette (int color_num, byte X_A = 8)
{
var source = ImageFormat.ReadColorMap (m_input.AsStream, color_num, PaletteFormat.RgbA);
var source = ImageFormat.ReadColorMap (m_input.AsStream,
color_num, X_A == 7 ? PaletteFormat.RgbA7 : X_A == 0 ? PaletteFormat.RgbX : PaletteFormat.RgbA);
var color_map = new Color[color_num];
if (color_num == 16){
Array.Copy(source, 0, color_map, 0, 16);
return new BitmapPalette(color_map);
}
int parts = color_num / 32;
const int blocks = 2;
const int rows = 2;

View File

@@ -0,0 +1,53 @@
using GameRes.Compression;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
namespace GameRes.Formats.DigitalWorks
{
[Export(typeof(ImageFormat))]
public class TM2ArkFormat : Tim2Format
{
public override string Tag { get { return "TIM2/PS2 compressed"; } }
public override string Description { get { return "PlayStation/2 image format with LZSS compress"; } }
public override uint Signature { get { return 0x535A4C; } } // 'LZS'
public TM2ArkFormat()
{
Extensions = new string[] { "tm2" };
Settings = null;
}
public override ImageMetaData ReadMetaData(IBinaryStream stream)
{
stream.Position = 9;
uint real_sign = stream.ReadUInt32();
//Tim2Format tm2raw = new Tim2Format();
if (real_sign != base.Signature)
{
return null;
}
stream.Position = 4;
uint unpacked_size = stream.ReadUInt32();
if (unpacked_size <= 0x20 || unpacked_size > 0x5000000) // ~83MB
return null;
stream.Position = 8;
using (var lzss = new LzssStream(stream.AsStream, LzssMode.Decompress, true))
using (var input = new SeekableStream(lzss))
using (var tm2 = new BinaryStream(input, stream.Name))
return base.ReadMetaData(tm2);
}
public override ImageData Read(IBinaryStream stream, ImageMetaData info)
{
stream.Position = 8;
using (var lzss = new LzssStream(stream.AsStream, LzssMode.Decompress, true))
using (var input = new SeekableStream(lzss))
using (var tm2 = new BinaryStream(input, stream.Name))
return base.Read(tm2, info);
}
public override void Write(Stream file, ImageData image)
{
throw new System.NotImplementedException("TM2ArkFormat.Write not implemented");
}
}
}

122
ArcFormats/Kid/ArcKLZ.cs Normal file
View File

@@ -0,0 +1,122 @@
using GameRes.Utility;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
namespace GameRes.Formats.Kid
{
[Export(typeof(ArchiveFormat))]
public class KlzOpener: ArchiveFormat
{
public override string Tag { get { return "KLZ/KID PS2"; } }
public override string Description { get { return "KID PS2 compressed image format with multi TIM2"; } }
public override uint Signature { get { return 0; } }
public override bool IsHierarchic { get { return false; } }
public override bool CanWrite { get { return false; } }
public KlzOpener()
{
Extensions = new string[] { "klz" };
}
public override ArcFile TryOpen(ArcView file)
{
if (!file.Name.HasExtension(".klz"))
return null;
uint unpacked_size = Binary.BigEndian(file.View.ReadUInt32(0));
if (unpacked_size <= 0x20 || unpacked_size > 0x5000000)
return null;
var backend = file.CreateStream();
var input = KlzFormat.LzhStreamDecode(backend);
var base_name = Path.GetFileNameWithoutExtension(file.Name);
var dir = GetEntries(input, base_name);
if (dir == null || dir.Count == 0)
{
return null;
}
else
{
return new KlzArchive(file, this, dir, input);
}
//throw new NotImplementedException();
}
public override Stream OpenEntry(ArcFile arc, Entry entry)
{
return new StreamRegion(((KlzArchive)arc).Source, entry.Offset, entry.Size, true);
}
internal static List<Entry> GetEntries (Stream input, string base_name)
{
var entries = new List<Entry>();
BinaryReader m_input = new ArcView.Reader(input);
int count = 0;
m_input.BaseStream.Position = 0;
while (m_input.BaseStream.Position < m_input.BaseStream.Length)
{
while (true)
{
try
{
uint sign = m_input.ReadUInt32();
m_input.ReadBytes(12);
if (sign == 0x324D4954) //TIM2
{
//m_input.BaseStream.Seek(-4, SeekOrigin.Current);
break;
}
}
catch (EndOfStreamException)
{
return entries;
}
}
long tell = m_input.BaseStream.Position - 16;
uint size = m_input.ReadUInt32() + 16;
string name = base_name + "_" + count.ToString("D2");
if (tell + size > m_input.BaseStream.Length)
{
size = (uint)(m_input.BaseStream.Length - tell);
name += "_incomplete";
}
var entry = new Entry {
Name = name + ".tm2",
Size = size,
Offset = tell,
Type = "image"
};
count++;
entries.Add(entry);
m_input.BaseStream.Position = tell + size;
}
return entries;
}
}
internal class KlzArchive : ArcFile
{
public readonly Stream Source;
public KlzArchive(ArcView arc, ArchiveFormat impl, ICollection<Entry> dir, Stream input)
: base (arc, impl, dir)
{
Source = input;
}
#region IDisposable Members
bool _spc_disposed = false;
protected override void Dispose(bool disposing)
{
if (_spc_disposed)
return;
if (disposing)
{
Source.Dispose();
}
_spc_disposed = true;
base.Dispose(disposing);
}
#endregion
}
}

313
ArcFormats/Kid/ImageKLZ.cs Normal file
View File

@@ -0,0 +1,313 @@
using GameRes.Utility;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
namespace GameRes.Formats.Kid
{
[Export(typeof(ImageFormat))]
public class KlzFormat: DigitalWorks.Tim2Format
{
public override string Tag { get { return "KLZ/KID PS2 compressed TIM2"; } }
public override string Description { get { return "KID PS2 compressed TIM2 image format"; } }
public override uint Signature { get { return 0; } } //KLZ have no header
public KlzFormat()
{
Extensions = new string[] { "klz" };
Settings = null;
}
public override ImageMetaData ReadMetaData(IBinaryStream stream)
{
uint unpacked_size = Binary.BigEndian(stream.Signature);
if (unpacked_size <= 0x20 || unpacked_size > 0x5000000) // ~83MB
return null;
stream.Position = 0;
//Stream streamdec = LzsStreamDecode(stream);
//using (var lzss = new LzssStream(stream.AsStream, LzssMode.Decompress, true))
using (var input = new SeekableStream(LzhStreamDecode(stream)))
using (var tm2 = new BinaryStream(input, stream.Name))
return base.ReadMetaData(tm2);
}
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(LzhStreamDecode(stream)))
using (var tm2 = new BinaryStream(input, stream.Name))
return base.Read(tm2, info);
}
public override void Write(Stream file, ImageData image)
{
throw new System.NotImplementedException("KlzFormat.Write not implemented");
}
/// <summary>
/// Original lzh_decode_mips
/// </summary>
/// The following code is from punk7890/PS2-Visual-Novel-Tool under MIT license.
/// Source code: https://github.com/punk7890/PS2-Visual-Novel-Tool/blob/ac5602fbf13d15ce1bfaa27dc2263373cfebc0e5/src/scenes/kid.gd#L104
/// <param name="input">input stream, include header</param>
/// <returns></returns>
public static Stream LzhStreamDecode(IBinaryStream input) {
byte[] out_bytes = new byte[0x4000];
List<byte> f_out_bytes = new List<byte>();
uint output_size = Binary.BigEndian(input.ReadUInt32());
ushort fill_count = Binary.BigEndian(input.ReadUInt16());
bool at;
int v0, s0 = 0, s1, s3;
byte v1; //byte a0
ushort s2;
int OO40_sp = 0, OO42_sp = 0, OO44_sp, OO48_sp, OO50_sp = 0, OO60_sp = 0, OO70_sp = fill_count;
int next_read_pos = 0;
int count = 0;
int num_passes = 0;
byte[] decode_table = new byte[] {
0x01, 0x02, 0x04, 0x08,
0x10, 0x20, 0x40, 0x80,
// Only first 8 are used
0x81, 0x75, 0x81, 0x69,
0x00, 0x00, 0x00, 0x00,
0x01, 0x02, 0x00, 0x00
};
// out.resize(0x4000)
/*int temp = 0x4000;
while (temp > 0)
{
out_bytes.Add(0);
temp--;
}*/
//out_bytes = Enumerable.Repeat((byte)0, 0x4000);
// out.resize(0x4000) end
if (fill_count > 0x4000)
{
next_read_pos = 4;
while (OO70_sp > 0x4000)
{
int cnt = 0;
int copy_off = next_read_pos + 2;
while (cnt < 0x4000)
{
input.Position = copy_off;
f_out_bytes.Add(input.ReadUInt8());
cnt++;
copy_off++;
}
count += 0x4000;
next_read_pos += cnt + 2;
num_passes++;
input.Position = next_read_pos;
OO70_sp = Binary.BigEndian(input.ReadUInt16());
if (count >= output_size || next_read_pos >= input.Length)
{
Stream stream = new MemoryStream(f_out_bytes.ToArray());
return stream;
}
OO60_sp = next_read_pos + 2;
}
}
else
{
OO60_sp = 6;
}
OO44_sp = OO60_sp;
/*v0 = OO60_sp + 1;
OO48_sp = v0;*/
OO48_sp = OO60_sp + 1;
while (true){
input.Position = OO44_sp;
//input.Seek(OO44_sp, SeekOrigin.Begin);
/*v0 = input.ReadUInt8();
a0 = v0 & 0xFF;*/
//a0 = input.ReadUInt8();
/*v0 = OO40_sp;
v1 = v0 & 0xFF;*/
v0 = decode_table[OO40_sp & 0xFF] & input.ReadUInt8();
//v0 &= a0;
// #001BA8AC
if (v0 == 0)
{
input.Position = OO48_sp;
//input.Seek(OO48_sp, SeekOrigin.Begin);
v1 = input.ReadUInt8();
v0 = OO50_sp + s0;
/*out_bytes.RemoveAt(v0);
out_bytes.Insert(v0, v1);*/
out_bytes[v0] = v1;
OO48_sp++;
OO42_sp++;
s0++;
}
else if (v0 != 0) {
// # 001BA8F0
OO42_sp += 2;
input.Position = OO48_sp;
// input.Seek(OO48_sp, SeekOrigin.Begin);
/*v0 = input.ReadUInt8() & 0xFF;
v1 = v0 << 8;
v0 = input.ReadUInt8() & 0xFF;
v0 = v1 | v0;
v0 &= 0xFFFF;*/
s2 = Binary.BigEndian(input.ReadUInt16());
/*s2 = v0 & 0xFFFF;
v0 = s2 & 0xFFFF;*/
//v0 = s2;
//v0 = (s2 & 0x1F);
//v0 += 2;
//v0 &= 0xFFFF;
/*s3 = v0 & 0xFFFF;
v0 = s2 & 0xFFFF;*/
s3 = (s2 & 0x1F) + 2;
//v0 = s2;
//v0 >>= 5;
/*v0 &= 0xFFFF;
s1 = v0 & 0xFFFF;
v0 = s1 & 0xFFFF;*/
v0 = s0 - (s2 >> 5) - 1;
//v0 -= 1;
//v0 &= 0xFFFF;
s1 = v0 & 0xFFFF;
OO48_sp += 1;
v0 = 1;
while (v0 != 0)
{
at = s0 < 0x0800;
// # 001BA96C
if (at)
{
v0 = s1 & 0xFFFF;
at = s0 < v0;
if (at)
{
v1 = out_bytes[OO50_sp];
v0 = OO50_sp + s0;
/*out_bytes.RemoveAt(v0);
out_bytes.Insert(v0, v1);*/
out_bytes[v0] = v1;
s0 += 1;
/*v0 = s1 + 1;
s1 = v0 & 0xFFFF;*/
s1 = (s1 + 1) & 0xFFFF;
// # 001BA9D8
/*v1 = s3;
v0 = v1 - 1;
s3 = v0 & 0xFFFF;
v0 = v1 & 0xFFFF;*/
v0 = s3 & 0xFFFF;
s3 = (s3 - 1) & 0xFFFF;
continue;
}
}
// # 001BA9B0
/*v1 = s1 & 0xFFFF;
v0 = OO50_sp;
v0 += v1;*/
//v0 = OO50_sp + s1 & 0xFFFF;
//v1 = out_bytes[v0];
v1 = out_bytes[OO50_sp + s1 & 0xFFFF];
v0 = OO50_sp;
v0 += s0;
/*out_bytes.RemoveAt(v0);
out_bytes.Insert(v0, v1);*/
out_bytes[v0] = v1;
s0 += 1;
//v0 = s1 + 1;
s1 = (s1 + 1) & 0xFFFF;
// # 001BA9D8
/*v1 = s3;
v0 = v1 - 1;
s3 = v0 & 0xFFFF;
v0 = v1 & 0xFFFF;*/
v0 = s3 & 0xFFFF;
s3 = s3 - 1 & 0xFFFF;
}
OO48_sp += 1;
}
// # 001BAA00
OO40_sp += 1;
//v1 = Convert.ToByte(OO40_sp & 0xFF);
//v0 = 8;
if ((OO40_sp & 0xFF) == 8)
{
OO40_sp = 0;
OO44_sp = OO48_sp;
OO48_sp += 1;
OO42_sp += 1;
}
/*v0 = OO42_sp;
v1 = v0 & 0xFFFF;
v0 = OO70_sp;
v0 -= 1;*/
//v0 = v1 < v0 ? 1 : 0;
v0 = OO42_sp < OO70_sp - 1 ? 1 : 0;
if (v0 == 0)
{
count += s0;
if (count >= output_size || next_read_pos >= input.Length)
{
f_out_bytes.AddRange(out_bytes);
Stream stream = new MemoryStream(f_out_bytes.ToArray());
return stream;
}
num_passes += 1;
if (num_passes == 1)
{
next_read_pos += OO70_sp + 6;
}
else
{
next_read_pos += OO70_sp + 2;
}
f_out_bytes.AddRange(out_bytes);
// # out.fill(0);
input.Position = next_read_pos;
OO70_sp = Binary.BigEndian(input.ReadUInt16());
if (OO70_sp > 0x4000)
{
while (OO70_sp > 0x4000)
{
int cnt = 0;
int copy_off = next_read_pos + 2;
while (cnt < 0x4000)
{
input.Position = copy_off;
f_out_bytes.Add(input.ReadUInt8());
cnt += 1;
copy_off += 1;
}
count += 0x4000;
next_read_pos += cnt + 2;
input.Position = next_read_pos;
OO70_sp = Binary.BigEndian(input.ReadUInt16());
if (count >= output_size || next_read_pos >= input.Length)
{
Stream stream = new MemoryStream(f_out_bytes.ToArray());
return stream;
}
}
}
s0 = 0;
//s1 = 0;
OO50_sp = 0;
OO42_sp = 0;
OO48_sp = next_read_pos + 2;
if (OO48_sp > input.Length) {
Stream stream = new MemoryStream(f_out_bytes.ToArray());
return stream;
}
OO40_sp = 0;
OO60_sp = OO48_sp;
OO44_sp = OO60_sp;
v0 = OO60_sp + 1;
OO48_sp = v0;
}
}
//Stream stream_out = new MemoryStream(f_out_bytes.ToArray());
//return stream_out;
}
}
}

View File

@@ -11,7 +11,7 @@ namespace GameRes.Formats.MAGES
public override string Tag { get { return "ARC/Princess Soft ARC20"; } }
public override string Description { get { return "Princess Soft PS2 resource archive"; } }
public override uint Signature { get { return 0x20435241; } } // 'ARC\x20'
public override bool IsHierarchic { get { return false; } }
public override bool IsHierarchic { get { return true; } }
public override bool CanWrite { get { return false; } }
public override ArcFile TryOpen(ArcView file)

View File

@@ -837,5 +837,17 @@ namespace GameRes.Formats.Properties {
this["NexasEncodingCP"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("RGBA")]
public string TIM2AlphaFormat {
get {
return ((string)(this["TIM2AlphaFormat"]));
}
set {
this["TIM2AlphaFormat"] = value;
}
}
}
}

View File

@@ -206,5 +206,8 @@
<Setting Name="NexasEncodingCP" Type="System.Int32" Scope="User">
<Value Profile="(Default)">932</Value>
</Setting>
<Setting Name="TIM2AlphaFormat" Type="System.String" Scope="User">
<Value Profile="(Default)">RGBA</Value>
</Setting>
</Settings>
</SettingsFile>

View File

@@ -752,6 +752,16 @@ namespace GameRes.Formats.Strings {
}
}
/// <summary>
/// Looks up a localized string similar to Choose Tim2 image alpha format.
/// It can&apos;t be read correctly from the file.
/// </summary>
public static string Tim2AlphaFormat {
get {
return ResourceManager.GetString("Tim2AlphaFormat", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Hex number.
/// </summary>

View File

@@ -501,4 +501,8 @@ Choose encryption scheme or enter a passphrase.</comment>
<data name="ODNAudioSampleRate" xml:space="preserve">
<value>Default audio sampling rate</value>
</data>
<data name="Tim2AlphaFormat" xml:space="preserve">
<value>Tim2画像のAlpha形式を選択してください。
ファイルから正しく読み取ることができません。</value>
</data>
</root>

View File

@@ -401,4 +401,8 @@ Choose encryption scheme or enter a passphrase.</value>
<data name="ODNAudioSampleRate" xml:space="preserve">
<value>Default audio sampling rate</value>
</data>
<data name="Tim2AlphaFormat" xml:space="preserve">
<value>Choose Tim2 image alpha format.
It can't be read correctly from the file.</value>
</data>
</root>

View File

@@ -399,4 +399,8 @@
<data name="ODNAudioSampleRate" xml:space="preserve">
<value>默认音频采样率</value>
</data>
<data name="Tim2AlphaFormat" xml:space="preserve">
<value>选择Tim2图片透明度格式。
这无法从文件中正确获取。</value>
</data>
</root>

View File

@@ -208,6 +208,9 @@
<setting name="NexasEncodingCP" serializeAs="String">
<value>932</value>
</setting>
<setting name="TIM2AlphaFormat" serializeAs="String">
<value>RGBA</value>
</setting>
</GameRes.Formats.Properties.Settings>
</userSettings>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" /></startup>

View File

@@ -71,6 +71,8 @@ namespace GameRes
BgrX = 6,
RgbA = 9,
BgrA = 10,
RgbA7 = 55,
BgrA7 = 66,
}
public class ImageData
@@ -124,7 +126,8 @@ namespace GameRes
public static ImageData Create (ImageMetaData info, PixelFormat format, BitmapPalette palette,
Array pixel_data)
{
return Create (info, format, palette, pixel_data, (int)info.Width*((format.BitsPerPixel+7)/8));
return Create (info, format, palette, pixel_data,
format.BitsPerPixel == 4 ? (int)info.Width*format.BitsPerPixel/8 : (int)info.Width*((format.BitsPerPixel+7)/8));
}
public static ImageData CreateFlipped (ImageMetaData info, PixelFormat format, BitmapPalette palette,
@@ -215,12 +218,16 @@ namespace GameRes
Func<int, Color> get_color;
if (PaletteFormat.Bgr == format || PaletteFormat.BgrX == format)
get_color = x => Color.FromRgb (palette_data[x+2], palette_data[x+1], palette_data[x]);
else if (PaletteFormat.BgrA7 == format)
get_color = x => Color.FromArgb(palette_data[x+3] >= byte.MaxValue / 2 ? byte.MaxValue : (byte)(palette_data[x+3] << 1), palette_data[x+2], palette_data[x+1], palette_data[x]);
else if (PaletteFormat.BgrA == format)
get_color = x => Color.FromArgb (palette_data[x+3], palette_data[x+2], palette_data[x+1], palette_data[x]);
else if (PaletteFormat.RgbA == format)
get_color = x => Color.FromArgb (palette_data[x+3], palette_data[x], palette_data[x+1], palette_data[x+2]);
else if (PaletteFormat.RgbA7 == format)
get_color = x => Color.FromArgb (palette_data[x+3] >= byte.MaxValue / 2 ? byte.MaxValue : (byte)(palette_data[x+3] << 1), palette_data[x], palette_data[x+1], palette_data[x+2]);
else
get_color = x => Color.FromRgb (palette_data[x], palette_data[x+1], palette_data[x+2]);
get_color = x => Color.FromRgb (palette_data[x], palette_data[x+1], palette_data[x+2]);
for (int i = 0; i < colors; ++i)
{