Merge pull request #16 from ManicsteinerYX/master

Massive updates
This commit is contained in:
Crsky 2023-12-17 15:06:22 +08:00 committed by GitHub
commit a52d2f3e25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 971 additions and 19 deletions

View File

@ -127,9 +127,13 @@
<Compile Include="CsWare\AudioWAV.cs" />
<Compile Include="CsWare\ImageGDT.cs" />
<Compile Include="FC01\ArcBDT.cs" />
<Compile Include="FC01\ArcSCXA.cs" />
<Compile Include="FC01\BdtTables.cs" />
<Compile Include="GScripter\ArcDATA.cs" />
<Compile Include="Ism\ImagePNG.cs" />
<Compile Include="Kid\ArcDATRAW.cs" />
<Compile Include="Kid\ImageLBG.cs" />
<Compile Include="Kid\ImageSPC.cs" />
<Compile Include="Kogado\ArcARC.cs" />
<Compile Include="Ice\ImageIBM.cs" />
<Compile Include="Ice\ScriptISD.cs" />
@ -169,7 +173,15 @@
<Compile Include="Macromedia\AudioSND.cs" />
<Compile Include="Macromedia\DirectorFile.cs" />
<Compile Include="Macromedia\Palettes.cs" />
<Compile Include="MAGES\ArcARC20.cs" />
<Compile Include="MAGES\ArcFARC.cs" />
<Compile Include="MAGES\ArcGTF.cs" />
<Compile Include="MAGES\ArcLoveOnce.cs" />
<Compile Include="MAGES\ImageBIN.cs" />
<Compile Include="Mugi\ArcBIN.cs" />
<Compile Include="NipponIchi\ArcCASN.cs" />
<Compile Include="NipponIchi\ArcPSFS.cs" />
<Compile Include="NipponIchi\ImageNMT.cs" />
<Compile Include="NScripter\Script.cs" />
<Compile Include="Psp\ArcQPK.cs" />
<Compile Include="ScrPlayer\ImageIMG.cs" />
@ -310,8 +322,8 @@
<Compile Include="MyAdv\ArcPAC.cs" />
<Compile Include="Nekopack\ArcNEKO2.cs" />
<Compile Include="Nekopack\ArcNEKO3.cs" />
<Compile Include="NitroPlus\ArcLAY.cs" />
<Compile Include="NitroPlus\ArcMPK.cs" />
<Compile Include="MAGES\ArcLAY.cs" />
<Compile Include="MAGES\ArcMPK.cs" />
<Compile Include="NitroPlus\ArcNPP.cs" />
<Compile Include="Noesis\ArcIGA.cs" />
<Compile Include="NonColor\ArcMinato.cs" />

View File

@ -57,9 +57,9 @@ namespace GameRes.Formats.Cri
backend.Position = 4;
var lzss = new LzssStream (backend);
var input = new SeekableStream (lzss);
var base_name = Path.GetFileNameWithoutExtension(file.Name);
try
{
var base_name = Path.GetFileNameWithoutExtension (file.Name);
using (var spc = new XtxIndexBuilder (input, base_name))
{
spc.ReadIndex (0);
@ -71,8 +71,15 @@ namespace GameRes.Formats.Cri
}
catch
{
input.Dispose();
throw;
//input.Dispose();
//throw;
var dir = new List<Entry>();
var entry = Create<PackedEntry>(base_name);
entry.Offset = 0;
entry.Size = (uint)input.Length;
entry.Type = "image";
dir.Add(entry);
return new SpcArchive(file, this, dir, input);
}
}

View File

@ -33,7 +33,7 @@ namespace GameRes.Formats.Cri
[Export(typeof(ImageFormat))]
public class SpcFormat : XtxFormat
{
public override string Tag { get { return "SPC"; } }
public override string Tag { get { return "SPC/Xbox360"; } }
public override string Description { get { return "CRI MiddleWare compressed texture format"; } }
public override uint Signature { get { return 0; } }

View File

@ -65,6 +65,16 @@ namespace GameRes.Formats.BGI
return null;
if (0 != stream.ReadInt64())
return null;
if (flag == 0)
{
int stride = (int)width * ((bpp + 7) / 8);
var pixels = new byte[stride * (int)height];
int read = stream.Read(pixels, 0, pixels.Length);
if (read != pixels.Length)
return null;
}
return new BgiMetaData
{
Width = (uint)width,

View File

@ -0,0 +1,50 @@
using System.Collections.Generic;
using System.ComponentModel.Composition;
namespace GameRes.Formats.FC01
{
[Export(typeof(ArchiveFormat))]
public class SCXAOpener : ArchiveFormat
{
public override string Tag { get { return "ARC/SCXA Pia Carrot e Youkoso 4 Xbox360"; } }
public override string Description { get { return "Pia Carrot e Youkoso 4 Xbox360 resource archive"; } }
public override uint Signature { get { return 0x41584353; } } // 'SCXA'
public override bool IsHierarchic { get { return false; } }
public override bool CanWrite { get { return false; } }
public override ArcFile TryOpen(ArcView file)
{
uint datastart = file.View.ReadUInt32(4);
int count = file.View.ReadInt32(8);
if (!IsSaneCount(count))
return null;
uint tnstart = (uint)count * 4 + 12;
var dir = new List<Entry>(count);
uint index_offset;
for (int i = 0; i < count; ++i)
{
uint namestart = file.View.ReadUInt32(i * 4 + 12);
uint fstart = file.View.ReadUInt32(tnstart + namestart);
uint flength = file.View.ReadUInt32(tnstart + namestart + 4);
index_offset = tnstart + namestart + 8;
byte c;
List<byte> namebyte = new List<byte>();
while (true)
{
c = file.View.ReadByte((long)index_offset);
if (c == 0 | index_offset > datastart) break;
namebyte.Add(c);
index_offset++;
}
var name = System.Text.Encoding.ASCII.GetString(namebyte.ToArray());
var entry = Create<Entry>(name);
entry.Offset = datastart + fstart;
entry.Size = flength;
if (!entry.CheckPlacement(file.MaxOffset))
return null;
dir.Add(entry);
}
return new ArcFile(file, this, dir);
}
}
}

148
ArcFormats/Kid/ArcDATRAW.cs Normal file
View File

@ -0,0 +1,148 @@
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 DATRAWOpener : ArchiveFormat
{
public override string Tag { get { return "DAT/KID & MAGES PS2 DAT RAW"; } }
public override string Description { get { return "DAT/KID & MAGES PS2 DAT RAW"; } }
public override uint Signature { get { return 0; } } //actually zero
public override bool IsHierarchic { get { return false; } }
public override bool CanWrite { get { return false; } }
private static readonly uint dataEntryCount = 4096;
public override ArcFile TryOpen(ArcView file)
{
var archivename = Path.GetFileNameWithoutExtension(file.Name);
var dir = new List<Entry>();
for (int i = 0; i < dataEntryCount; i++)
{
uint offset = file.View.ReadUInt32(i * 8);
uint size = file.View.ReadUInt32(i * 8 + 4);
offset = offset * 2048 + 0x8000;
size *= 1024;
if (offset > file.MaxOffset || size > file.MaxOffset)
{
throw new InvalidFormatException();
}
if (size == 0) continue;
var entry = Create<Entry>(archivename + i.ToString("D5"));
entry.Offset = offset;
entry.Size = size;
dir.Add(entry);
}
return new ArcFile(file, this, dir);
}
/*public override Stream OpenEntry(ArcFile arc, Entry entry)
{
IBinaryStream input = arc.File.CreateStream(entry.Offset, entry.Size, entry.Name);
if (input.Signature == 0x535043) // 'CPS'
{
using (input)
return UnpackCps(input);
}
return input.AsStream;
}*/
Stream UnpackCps(IBinaryStream input)
{
var header = input.ReadHeader(0x10);
int packed_size = header.ToInt32(4);
int compression = header.ToUInt16(0xA);
int unpacked_size = header.ToInt32(0xC);
//input.Seek(-4, SeekOrigin.End);
input.Seek(packed_size - 4, SeekOrigin.Begin);
uint key_offset = input.ReadUInt32() - 0x7534682;
input.Position = key_offset;
uint key = input.ReadUInt32() + key_offset + 0x3786425;
var decryptor = new CpsTransform(packed_size, (int)key_offset, key);
using (var decoded = new InputCryptoStream(input.AsStream, decryptor))
using (var cps = new BinaryStream(decoded, input.Name))
{
var output = new byte[unpacked_size];
if ((compression & 1) != 0)
{
cps.ReadInt32();
UnpackLnd(cps, output);
}
else if ((compression & 2) != 0)
{
UnpackLnd16(cps, output);
}
else
{
cps.ReadInt32();
cps.Read(output, 0, unpacked_size);
}
return new BinMemoryStream(output);
}
}
internal static void UnpackLnd(IBinaryStream input, byte[] output)
{
int unpacked_size = output.Length;
int dst = 0;
while (dst < unpacked_size)
{
int ctl = input.ReadByte();
if (-1 == ctl)
break;
if ((ctl & 0x80) != 0)
{
if ((ctl & 0x40) != 0)
{
int count = (ctl & 0x1F) + 2;
if ((ctl & 0x20) != 0)
count += input.ReadUInt8() << 5;
count = Math.Min(count, unpacked_size - dst);
byte v = input.ReadUInt8();
for (int i = 0; i < count; ++i)
output[dst++] = v;
}
else
{
int count = ((ctl >> 2) & 0xF) + 2;
int offset = ((ctl & 3) << 8) + input.ReadUInt8() + 1;
count = Math.Min(count, unpacked_size - dst);
Binary.CopyOverlapped(output, dst - offset, dst, count);
dst += count;
}
}
else if ((ctl & 0x40) != 0)
{
int length = Math.Min((ctl & 0x3F) + 2, unpacked_size - dst);
int count = input.ReadUInt8();
input.Read(output, dst, length);
dst += length;
count = Math.Min(count * length, unpacked_size - dst);
if (count > 0)
{
Binary.CopyOverlapped(output, dst - length, dst, count);
dst += count;
}
}
else
{
int count = (ctl & 0x1F) + 1;
if ((ctl & 0x20) != 0)
count += input.ReadUInt8() << 5;
count = Math.Min(count, unpacked_size - dst);
input.Read(output, dst, count);
dst += count;
}
}
}
static void UnpackLnd16(IBinaryStream input, byte[] output)
{
throw new NotImplementedException("KID Lnd16 compression not implemented.");
}
}
}

111
ArcFormats/Kid/ImageLBG.cs Normal file
View File

@ -0,0 +1,111 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.IO;
namespace GameRes.Formats.Kid
{
[Export(typeof(ImageFormat))]
public class LbgFormat : ImageFormat
{
public override string Tag { get { return "LBG/PS2-SPC"; } }
public override string Description { get { return "KID PS2 SPC Image Format"; } }
public override uint Signature { get { return 0; } } //real signature may exist below
public LbgFormat()
{
Extensions = new string[] { "", "lbg" };
// Actually LBG format can contain more than one image as lip for chara, well, "not implemented".
}
public override ImageMetaData ReadMetaData(IBinaryStream file)
{
uint header = file.ReadUInt32();
uint overheader = 0;
if (header != 0x2047424C) //LBG\x20
{
overheader = header;
if (overheader > 0x50) //usually 10 or 30, never seen any larger
return null;
file.Seek(overheader, SeekOrigin.Begin);
header = file.ReadUInt32();
if (header != 0x2047424C) //LBG\x20
return null;
}
int width = file.ReadInt16();
int height = file.ReadInt16();
if (width <= 0 || height <= 0)
return null;
return new LbgImageMetaData
{
Width = (uint)width,
Height = (uint)height,
OverHeader = overheader,
};
}
public override ImageData Read(IBinaryStream file, ImageMetaData info)
{
if (info == null)
throw new NotSupportedException(string.Format("Not LBG texture format."));
/*if (info.Width != 640)
{
throw new NotSupportedException(string.Format("Not 640 pixels width, may not work."));
}*/
var lbgheader = (LbgImageMetaData)info;
uint oversize = 0;
uint blocknum = info.Width / 126;
if (lbgheader.OverHeader != 0)
{
file.Position = 4;
uint filesize = file.ReadUInt32();
if (filesize == 0)
oversize = 8;
else
{
filesize -= 16;
oversize = (filesize - info.Width * info.Height * 4) / info.Height / (blocknum + 1);
}
}
file.Position = lbgheader.OverHeader + 0x10;
//List<byte> pixels = new List<byte>();
byte[] pixels = new byte[info.Width * info.Height * 4];
for (int blockcount = 0; blockcount <= blocknum; blockcount++)
{
for (int y = 0; y < info.Height; y++)
{
for (int x = 0; (blockcount != blocknum & x < 126) | (blockcount == blocknum & x < info.Width - blockcount * 126); x++)
{
var pixel = file.ReadBytes(4); //RGBA with wrong A
long target = (x + blockcount * 126) * 4 + y * info.Width * 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); //needs a test
}
if (oversize != 0)
file.ReadBytes((int)oversize);
}
}
return ImageData.Create(info, PixelFormats.Bgra32, null, pixels);
}
public override void Write(Stream file, ImageData bitmap)
{
throw new NotImplementedException("LbgFormat.Write not implemented");
}
}
class LbgImageMetaData : ImageMetaData
{
public uint OverHeader { get; set; }
}
}

View File

@ -0,0 +1,44 @@
using GameRes.Compression;
using System.ComponentModel.Composition;
using System.IO;
namespace GameRes.Formats.Kid
{
[Export(typeof(ImageFormat))]
public class SpcFormat: LbgFormat
{
public override string Tag { get { return "SPC/PS2"; } }
public override string Description { get { return "PS2 CRI MiddleWare compressed texture format"; } }
public override uint Signature { get { return 0; } }
public SpcFormat()
{
Extensions = new string[] { "spc" };
}
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 lbg = new BinaryStream(input, stream.Name))
return base.ReadMetaData(lbg);
}
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 lbg = new BinaryStream(input, stream.Name))
return base.Read(lbg, info);
}
public override void Write(Stream file, ImageData image)
{
throw new System.NotImplementedException("SpcFormat.Write not implemented");
}
}
}

View File

@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Text;
namespace GameRes.Formats.MAGES
{
[Export(typeof(ArchiveFormat))]
public class ARC20Opener : ArchiveFormat
{
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 CanWrite { get { return false; } }
public override ArcFile TryOpen(ArcView file)
{
int count = file.View.ReadInt32(4);
if (!IsSaneCount(count))
return null;
uint filename_end = file.View.ReadUInt32(8);
var dir = new List<Entry>(count);
uint index_offset;
for (int i = 0; i < count; ++i)
{
index_offset = file.View.ReadUInt32(16 * i + 16);
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 = sjis.GetString(namebyte.ToArray());
var entry = Create<Entry>(name);
entry.Offset = file.View.ReadUInt32(16 * i + 16 + 4) * 2048;
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);
}
}
}

View File

@ -0,0 +1,48 @@
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Text;
namespace GameRes.Formats.MAGES
{
[Export(typeof(ArchiveFormat))]
public class FARCOpener : ArchiveFormat
{
public override string Tag { get { return "DAT/FARC Rozen Maiden PS3 archive"; } }
public override string Description { get { return "MAGES Rozen Maiden Wechseln Sie Welt ab PS3 BLJM61120 archive"; } }
public override uint Signature { get { return 0x43524146; } } // 'FARC'
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(20);
if (!IsSaneCount(count))
return null;
uint datanamestart = (uint)count * 20 + 36;
var dir = new List<Entry>(count);
for (int i = 0; i < count; ++i)
{
long namepl = file.View.ReadUInt32(20 * i + 36 + 16);
long index_offset = datanamestart + namepl;
byte c;
List<byte> namebyte = new List<byte>();
while (true)
{
c = file.View.ReadByte(index_offset);
if (c == 0) break;
namebyte.Add(c);
index_offset++;
}
var sjis = Encoding.GetEncoding("Shift-JIS");
var name = sjis.GetString(namebyte.ToArray());
var entry = Create<Entry>(name);
entry.Offset = file.View.ReadUInt32(20 * i + 36);
entry.Size = file.View.ReadUInt32(20 * i + 36 + 4);
if (entry.Size == 0)
continue;
dir.Add(entry);
}
return new ArcFile(file, this, dir);
}
}
}

116
ArcFormats/MAGES/ArcGTF.cs Normal file
View File

@ -0,0 +1,116 @@
using GameRes.Utility;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Xml.Linq;
namespace GameRes.Formats.MAGES
{
[Export(typeof(ArchiveFormat))]
public class GTFOpener : ArchiveFormat
{
public override string Tag { get { return "GTF/Rozen Maiden PS3 Image archive"; } }
public override string Description { get { return "MAGES Rozen Maiden Wechseln Sie Welt ab PS3 BLJM61120 Image archive"; } }
public override uint Signature { get { return 0xFF000202; } } // 'FF000202'
public override bool IsHierarchic { get { return false; } }
public override bool CanWrite { get { return false; } }
public override ArcFile TryOpen(ArcView file)
{
int count = Binary.BigEndian(file.View.ReadInt32(8));
if (!IsSaneCount(count))
return null;
string filename = Path.GetFileNameWithoutExtension(file.Name);
var dir = new List<Entry>(count);
for (int i = 0; i < count; i++)
{
var entry = Create<Entry_RawImage>(filename + '_' + i.ToString());
entry.Offset = Binary.BigEndian(file.View.ReadUInt32(16 + 36 * i));
entry.Size = Binary.BigEndian(file.View.ReadUInt32(16 + 36 * i + 4));
entry.width = Binary.BigEndian(file.View.ReadUInt16(32 + 36 * i));
entry.height = Binary.BigEndian(file.View.ReadUInt16(32 + 36 * i + 2));
entry.Type = "image";
dir.Add(entry);
}
return new ArcFile(file, this, dir);
}
public override Stream OpenEntry(ArcFile arc, Entry entry)
{
var compentry = (Entry_RawImage)entry;
IBinaryStream input = arc.File.CreateStream(entry.Offset, entry.Size, entry.Name);
return ReadImageGTF(input, compentry.width, compentry.height);
}
internal class Entry_RawImage : Entry
{
public ushort width { get; set; }
public ushort height { get; set; }
}
/*[Export(typeof(ImageFormat))]
public class GTFFormat : ImageFormat
{
public override string Tag { get { return "MAGES PS3/PSV Image Format"; } }
public override string Description { get { return "MAGES PS3/PSV Image Format"; } }
public override uint Signature { get { return 0; } }
public override ImageMetaData ReadMetaData(IBinaryStream file)
{
throw new System.NotImplementedException();
}
public override ImageData Read(IBinaryStream file, ImageMetaData info)
{
throw new System.NotImplementedException();
}
public override void Write(Stream file, ImageData bitmap)
{
throw new System.NotImplementedException();
}
}*/
/// <summary>
/// This method returns MAGES/ImageBIN format Image data stream, please ensure it's decoding method exists.
/// </summary>
/// <param name="input">GTF or BIN raw ARGB32 data, start in the upper left corner, each row.</param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <returns>MAGES/ImageBIN format Image data stream</returns>
static Stream ReadImageGTF(IBinaryStream input, ushort width, ushort height)
{
//List<byte> bytes = new List<byte>();
byte[] widths = BitConverter.GetBytes(width);
byte[] heights = BitConverter.GetBytes(height);
byte[] bpp = BitConverter.GetBytes((uint)32);
/*Stream output = new MemoryStream();
output.Write(widths, 0, widths.Length);
output.Write(heights, 0, heights.Length);
output.Write(bpp, 0, bpp.Length);
output.Write(input.ReadBytes((int)input.Length), 0, (int)input.Length);
byte[] bytes = new byte[output.Length];
output.Seek(0, SeekOrigin.Begin);
output.Read(bytes, 0, bytes.Length);
output.Dispose();*/
byte[] inputData = input.ReadBytes((int)input.Length);
byte[] outputData = new byte[widths.Length + heights.Length + bpp.Length + inputData.Length];
Buffer.BlockCopy(widths, 0, outputData, 0, widths.Length);
Buffer.BlockCopy(heights, 0, outputData, widths.Length, heights.Length);
Buffer.BlockCopy(bpp, 0, outputData, widths.Length + heights.Length, bpp.Length);
Buffer.BlockCopy(inputData, 0, outputData, widths.Length + heights.Length + bpp.Length, inputData.Length);
return new BinMemoryStream(outputData);
/*List<byte> pixels = new List<byte>();
for (int i = 0; i < input.Length; i++)
{
var pixel = input.ReadBytes(4); //ARGB
//BGRA
pixels.Add(pixel[3]);
pixels.Add(pixel[2]);
pixels.Add(pixel[1]);
pixels.Add(pixel[0]);
}*/
}
}
}

View File

@ -32,7 +32,7 @@ using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace GameRes.Formats.NitroPlus
namespace GameRes.Formats.MAGES
{
internal class LayEntry : Entry
{

View File

@ -0,0 +1,57 @@
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Runtime.CompilerServices;
using System.Xml.Linq;
namespace GameRes.Formats.MAGES
{
[Export(typeof(ArchiveFormat))]
public class LoveOnceOpener : ArchiveFormat
{
public override string Tag { get { return "BIN/LoveOnce"; } }
public override string Description { get { return "L@ve Once PS3 resource archive"; } }
public override uint Signature { get { return 0; } } // no header
public override bool IsHierarchic { get { return false; } }
public override bool CanWrite { get { return false; } }
public override ArcFile TryOpen(ArcView filedata)
{
ArcView filelist;
if (filedata.Name.EndsWith("data.bin"))
{
string filepath = Path.GetDirectoryName(filedata.Name);
filepath = Path.Combine(filepath, "list.bin");
if (! File.Exists(filepath)) return null;
filelist = new ArcView(filepath);
}
else if (filedata.Name.EndsWith("list.bin"))
{
string filepath = Path.GetDirectoryName(filedata.Name);
filepath = Path.Combine(filepath, "data.bin");
if (!File.Exists(filepath)) return null;
filelist = new ArcView(filepath);
return TryOpen(filelist);
}
else return null;
uint index_offset = 0, count = 0;
var dir = new List<Entry>();
while (index_offset < filelist.MaxOffset)
{
uint filesize = filelist.View.ReadUInt32(index_offset);
uint fileoffset = filelist.View.ReadUInt32(index_offset + 8);
string name = filelist.View.ReadString(index_offset + 0x10, 0x40);
var entry = Create<Entry>(name);
entry.Size = filesize;
entry.Offset = fileoffset;
if (!entry.CheckPlacement(filedata.MaxOffset))
return null;
dir.Add(entry);
count++;
index_offset += 0x50;
}
return new ArcFile(filedata, this, dir);
}
}
}

View File

@ -26,7 +26,7 @@
using System.Collections.Generic;
using System.ComponentModel.Composition;
namespace GameRes.Formats.NitroPlus
namespace GameRes.Formats.MAGES
{
[Export(typeof(ArchiveFormat))]
public class MpkOpener : ArchiveFormat
@ -39,11 +39,31 @@ namespace GameRes.Formats.NitroPlus
public override ArcFile TryOpen (ArcView file)
{
uint version_temp = file.View.ReadUInt32 (4);
int count = file.View.ReadInt32 (8);
if (!IsSaneCount (count))
return null;
uint index_offset = 0x48;
var dir = new List<Entry> (count);
uint index_offset = 0;
if (version_temp == 65536)
{
index_offset = 0x44;
for (int i = 0; i < count; ++i)
{
var name = file.View.ReadString (index_offset+0x1c, 0xE0);
var entry = Create<PackedEntry> (name);
entry.Offset = file.View.ReadInt32 (index_offset);
entry.Size = file.View.ReadUInt32 (index_offset+4);
entry.UnpackedSize = file.View.ReadUInt32 (index_offset+8);
if (!entry.CheckPlacement (file.MaxOffset))
return null;
dir.Add (entry);
index_offset += 0x100;
}
}
else
{
index_offset = 0x48;
for (int i = 0; i < count; ++i)
{
var name = file.View.ReadString (index_offset+0x18, 0xE0);
@ -56,6 +76,7 @@ namespace GameRes.Formats.NitroPlus
dir.Add (entry);
index_offset += 0x100;
}
}
return new ArcFile (file, this, dir);
}
}

View File

@ -0,0 +1,143 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics.Eventing.Reader;
using System.IO;
using System.Text;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace GameRes.Formats.MAGES
{
[Export(typeof(ImageFormat))]
public class BinFormat : ImageFormat
{
public override string Tag { get { return "MAGES PS3/PSV Image Format"; } }
public override string Description { get { return "MAGES PS3/PSV Image Format"; } }
public override uint Signature { get { return 0; } }
public override bool CanWrite { get { return true; } }
public BinFormat()
{
Extensions = new string[] { "" };
}
public override ImageMetaData ReadMetaData(IBinaryStream file)
{
//var header = file.ReadHeader(8);
int width = file.ReadInt16();
int height = file.ReadInt16();
if (width <= 0 || height <= 0)
return null;
int bpp = file.ReadInt16();
if (32 == bpp)
{
uint imagedatasize = (uint)width * (uint)height * 4;
if (file.Length != imagedatasize + 8)
return null;
}
else if (8 == bpp)
{
uint imagedatasize = (uint)width * (uint)height + 256;
if (file.Length != imagedatasize + 8)
return null;
}
else
return null;
return new ImageMetaData
{
Width = (uint)width,
Height = (uint)height,
BPP = bpp,
};
}
public override ImageData Read(IBinaryStream file, ImageMetaData info)
{
if (info == null)
throw new NotSupportedException(string.Format("Not BIN texture format."));
if (info.BPP == 32)
{
uint pixelnum = info.Width * info.Height;
if (file.Length != pixelnum * 4 + 8) throw new NotSupportedException(string.Format("Not BIN 32ARGB texture format."));
file.Position = 8;
//var data = file.ReadBytes(info.iWidth * info.iHeight * 4);
List<byte> pixels = new List<byte>();
for (int i = 0; i < pixelnum; i++)
{
var pixel = file.ReadBytes(4); //ARGB
//BGRA
pixels.Add(pixel[3]);
pixels.Add(pixel[2]);
pixels.Add(pixel[1]);
pixels.Add(pixel[0]);
}
return ImageData.Create(info, PixelFormats.Bgra32, null, pixels.ToArray());
}
else if (info.BPP == 8)
{
uint imagedatasize = info.Width * info.Height + 256;
if (file.Length != imagedatasize + 8) throw new NotSupportedException(string.Format("Not BIN 256colors texture format."));
file.Position = 8;
//var pixelColor = file.ReadBytes(256 * 4);
List<Color> colors = new List<Color>();
for (int i = 0; i < 256; i += 4)
{
Color c = new Color();
var color_b = file.ReadBytes(4); //BGRA
c.B = color_b[0];
c.G = color_b[1];
c.R = color_b[2];
c.A = color_b[3];
colors.Add(c);
}
BitmapPalette palette = new BitmapPalette(colors);
//file.Position += 256 * 4;
var data = file.ReadBytes(info.iWidth * info.iHeight);
return ImageData.Create(info, PixelFormats.Indexed8, palette, data);
}
else
throw new NotSupportedException(string.Format("Not BIN texture format."));
}
public override void Write(Stream stream, ImageData image)
{
//throw new System.NotImplementedException("BINFormat.Write not implemented");
using (var file = new BinaryWriter(stream, Encoding.ASCII, true))
{
if (image.Width > ushort.MaxValue || image.Height > ushort.MaxValue)
{
throw new NotSupportedException(string.Format("Image width or height oversize."));
}
if (image.BPP != 32)
{
throw new NotSupportedException(string.Format("Image bitdepth not supported, should be 32."));
}
file.Write((ushort)image.Width);
file.Write((ushort)image.Height);
file.Write(image.BPP);
var bitmap = image.Bitmap;
if (bitmap.Format != PixelFormats.Bgra32)
{
bitmap = new FormatConvertedBitmap(image.Bitmap, PixelFormats.Bgra32, null, 0);
}
int stride = (int)image.Width * 4;
byte[] row_data = new byte[stride];
Int32Rect rect = new Int32Rect(0, 0, (int)image.Width, 1);
for (uint row = 0; row < image.Height; ++row)
{
bitmap.CopyPixels(rect, row_data, stride, 0);
for (uint col = 0; col < image.Width; ++col)
{
(row_data[(col * 4) + 3], row_data[col * 4]) = (row_data[col * 4], row_data[(col * 4) + 3]);
(row_data[(col * 4) + 2], row_data[(col * 4) + 1]) = (row_data[(col * 4) + 1], row_data[(col * 4) + 2]);
}
file.Write(row_data);
rect.Y++;
}
}
}
}
}

View File

@ -0,0 +1,50 @@
using GameRes.Utility;
using System.Collections.Generic;
using System.ComponentModel.Composition;
namespace GameRes.Formats.NipponIchi
{
[Export(typeof(ArchiveFormat))]
public class CASNOpener : ArchiveFormat
{
public override string Tag { get { return "DAT/CASN ShinHayarigami"; } }
public override string Description { get { return "Nippon Ichi Shin Hayarigami PS3 resource archive"; } }
public override uint Signature { get { return 0x4E534143; } } // 'CASN'
public override bool IsHierarchic { get { return false; } }
public override bool CanWrite { get { return false; } }
public override ArcFile TryOpen(ArcView file)
{
int count = Binary.BigEndian(file.View.ReadUInt16(6));
if (!IsSaneCount(count))
return null;
long index_offset = count * 10 + 30; //actually count*10 + 28, ignored two bytes of 000C or 000B
var dir = new List<Entry>(count);
for (int i = 0; i < count; ++i)
{
uint fstart = Binary.BigEndian(file.View.ReadUInt32(index_offset));
uint flength = Binary.BigEndian(file.View.ReadUInt32(index_offset + 4));
index_offset += 8;
byte c;
List<byte> namebyte = new List<byte>();
while (true)
{
c = file.View.ReadByte(index_offset);
if (c == 0) break;
namebyte.Add(c);
index_offset++;
}
index_offset += 3;
//var sjis = System.Text.Encoding.GetEncoding("Shift-JIS");
var name = System.Text.Encoding.ASCII.GetString(namebyte.ToArray());
var entry = Create<Entry>(name);
entry.Offset = fstart;
entry.Size = flength;
if (!entry.CheckPlacement(file.MaxOffset))
return null;
dir.Add(entry);
}
return new ArcFile(file, this, dir);
}
}
}

View File

@ -0,0 +1,42 @@
using GameRes.Utility;
using System.Collections.Generic;
using System.ComponentModel.Composition;
namespace GameRes.Formats.NipponIchi
{
[Export(typeof(ArchiveFormat))]
public class PSFSOpener : ArchiveFormat
{
public override string Tag { get { return "DAT/PS_FS ShinHayarigami2"; } }
public override string Description { get { return "Nippon Ichi Shin Hayarigami2 PS3 resource archive"; } }
public override uint Signature { get { return 0x465F5350; } } // 'PS_F' of 'PS_FS_V1'
public override bool IsHierarchic { get { return false; } }
public override bool CanWrite { get { return false; } }
public override ArcFile TryOpen(ArcView file)
{
int count = Binary.BigEndian(file.View.ReadInt32(8));
if (!IsSaneCount(count))
return null;
long index_offset = 0x10;
var dir = new List<Entry>(count);
for (int i = 0; i < count; ++i)
{
string name = file.View.ReadString(index_offset, 0x30);
var entry = Create<Entry>(name);
entry.Offset = Binary.BigEndian(file.View.ReadUInt32(index_offset + 0x3C));
entry.Size = Binary.BigEndian(file.View.ReadUInt32(index_offset + 0x34));
index_offset += 0x40;
if (!entry.CheckPlacement(file.MaxOffset))
return null;
if (0 == file.View.ReadByte(entry.Offset))
{
entry.Offset += 0x10;
entry.Size -= 0x10;
}
dir.Add(entry);
}
return new ArcFile(file, this, dir);
}
}
}

View File

@ -0,0 +1,39 @@
using System;
using System.ComponentModel.Composition;
using System.IO;
using System.Windows.Media;
namespace GameRes.Formats.NipponIchi
{
[Export(typeof(ImageFormat))]
public class NmtFormat : ImageFormat {
public override string Tag { get { return "NMT"; } }
public override string Description { get { return "NIS Multy Texform image format"; } }
public override uint Signature { get { return 0x6D73696E; } } // 'nism'
public override ImageMetaData ReadMetaData(IBinaryStream file)
{
var header = file.ReadHeader(0x30);
var signature = file.ReadHeader(15);
if (System.Text.Encoding.ASCII.GetString(signature.ToArray()) != "nismultitexform")
return null;
return new ImageMetaData
{
Width = header.ToUInt16(0x26),
Height = header.ToUInt16(0x28)
};
}
public override ImageData Read(IBinaryStream file, ImageMetaData info)
{
//uint imagedatasize = info.Width * info.Height * 4;
if (info == null) throw new NotSupportedException(string.Format("Not NMT texture format."));
file.Position = 0x30;
var data = file.ReadBytes(info.iWidth * info.iHeight * 4);
return ImageData.Create(info, PixelFormats.Bgra32, null, data);
}
public override void Write(Stream file, ImageData image)
{
throw new System.NotImplementedException("NmtFormat.Write not implemented");
}
}
}

View File

@ -100,6 +100,10 @@
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>If $(ConfigurationName) == Release del *.pdb
If $(ConfigurationName) == Release del *.config</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">