1
0
mirror of synced 2024-11-28 01:10:51 +01:00

Wip zar, gar,, and more rarc saving progress

This commit is contained in:
KillzXGaming 2019-07-25 16:49:04 -04:00
parent 40c0fcae11
commit e0df03cc26
22 changed files with 897 additions and 109 deletions

Binary file not shown.

View File

@ -0,0 +1,237 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Toolbox;
using System.Windows.Forms;
using Toolbox.Library;
using Toolbox.Library.IO;
namespace FirstPlugin
{
public class ZAR : IArchiveFile, IFileFormat
{
public FileType FileType { get; set; } = FileType.Archive;
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Zelda/Grezzo Archive" };
public string[] Extension { get; set; } = new string[] { "*.zar", "*.gar" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool CanAddFiles { get; set; }
public bool CanRenameFiles { get; set; }
public bool CanReplaceFiles { get; set; }
public bool CanDeleteFiles { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Toolbox.Library.IO.FileReader(stream, true))
{
return reader.CheckSignature(4, "ZAR/x01") || reader.CheckSignature(4, "GAR\x02") || reader.CheckSignature(4, "GAR\x05");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public List<FileEntry> files = new List<FileEntry>();
public IEnumerable<ArchiveFileInfo> Files => files;
public void ClearFiles() { files.Clear(); }
public enum VersionMagic
{
ZAR1, //OOT3D
GAR2, //MM3D
GAR5, //LM3DS
}
public Header header;
public void Load(System.IO.Stream stream)
{
header = new Header();
header.Read(new FileReader(stream), files);
}
public class Header
{
public VersionMagic Version;
public uint FileSize;
public ushort FileGroupCount;
public ushort FileCount;
public uint FileGroupOffset;
public uint FileInfoOffset;
public uint DataOffset;
public string Codename;
public List<FileGroup> FileGroups = new List<FileGroup>();
public List<GarFileInfo> GarFileInfos = new List<GarFileInfo>();
public void Read(FileReader reader, List<FileEntry> files)
{
reader.ByteOrder = Syroot.BinaryData.ByteOrder.LittleEndian;
string Signature = reader.ReadString(4, Encoding.ASCII);
switch (Signature)
{
case "ZAR\x01":
Version = VersionMagic.ZAR1;
break;
case "GAR\x02":
Version = VersionMagic.GAR2;
break;
case "GAR\x05":
Version = VersionMagic.GAR5;
break;
}
FileSize = reader.ReadUInt32();
FileGroupCount = reader.ReadUInt16();
FileCount = reader.ReadUInt16();
FileGroupOffset = reader.ReadUInt32();
FileInfoOffset = reader.ReadUInt32();
DataOffset = reader.ReadUInt32();
Codename = reader.ReadString(0x08);
switch (Codename)
{
case "queen\0\0\0":
case "jenkins\0":
ReadZeldaArchive(reader, files);
break;
case "agora\0\0\0":
case "SYSTEM\0\0":
ReadGrezzoArchive(reader, files);
break;
default:
throw new Exception($"Unexpected codename! {Codename}");
}
}
private void ReadGrezzoArchive(FileReader reader, List<FileEntry> files)
{
}
private void ReadZeldaArchive(FileReader reader, List<FileEntry> files)
{
reader.SeekBegin(FileGroupOffset);
for (int i = 0; i < FileGroupCount; i++)
FileGroups.Add(new FileGroup(reader));
for (int i = 0; i < FileGroupCount; i++)
FileGroups[i].Ids = reader.ReadInt32s((int)FileGroups[i].FileCount);
reader.SeekBegin(FileInfoOffset);
for (int i = 0; i < FileGroupCount; i++)
{
for (int f = 0; f < FileGroups[i].FileCount; f++)
GarFileInfos.Add(new GarFileInfo(reader));
}
reader.SeekBegin(DataOffset);
uint[] Offsets = reader.ReadUInt32s(FileCount);
for (int i = 0; i < GarFileInfos.Count; i++)
{
files.Add(new FileEntry()
{
FileName = GarFileInfos[i].FileName,
FileData = reader.getSection(Offsets[i], GarFileInfos[i].FileSize)
});
}
}
public class FileGroup
{
public uint FileCount;
public uint DataOffset;
public uint InfoOffset;
public int[] Ids;
public FileGroup(FileReader reader)
{
FileCount = reader.ReadUInt32();
DataOffset = reader.ReadUInt32();
InfoOffset = reader.ReadUInt32();
reader.ReadUInt32();
}
}
public class ZarFileInfo
{
public uint FileSize;
public string FileName;
public ZarFileInfo(FileReader reader)
{
FileSize = reader.ReadUInt32();
FileName = reader.LoadString(false, typeof(uint));
}
}
public class GarFileInfo
{
public uint FileSize;
public string FileName;
public string Name;
public GarFileInfo(FileReader reader)
{
FileSize = reader.ReadUInt32();
Name = reader.LoadString(false, typeof(uint));
FileName = reader.LoadString(false, typeof(uint));
}
}
}
public void Unload()
{
}
public byte[] Save()
{
return null;
}
public bool AddFile(ArchiveFileInfo archiveFileInfo)
{
return false;
}
public bool DeleteFile(ArchiveFileInfo archiveFileInfo)
{
return false;
}
public class FileEntry : ArchiveFileInfo
{
public uint Unknown { get; set; }
internal uint Size;
internal uint Offset;
internal uint NameOffset;
public void Read(FileReader reader)
{
uint Unknown = reader.ReadUInt32();
NameOffset = reader.ReadUInt32();
Offset = reader.ReadUInt32();
Size = reader.ReadUInt32();
}
}
}
}

View File

@ -0,0 +1,145 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Toolbox;
using System.Windows.Forms;
using Toolbox.Library;
using Toolbox.Library.IO;
namespace FirstPlugin
{
//Information on this file from noclip
//https://github.com/magcius/noclip.website/blob/master/src/oot3d/zsi.ts
public class ZSI : TreeNodeFile, IFileFormat
{
public FileType FileType { get; set; } = FileType.Archive;
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Zelda Scene Information (OOT3D/MM3D)" };
public string[] Extension { get; set; } = new string[] { "*.zsi" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool CanAddFiles { get; set; }
public bool CanRenameFiles { get; set; }
public bool CanReplaceFiles { get; set; }
public bool CanDeleteFiles { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Toolbox.Library.IO.FileReader(stream, true))
{
return reader.CheckSignature(4, "ZSI\x01") || reader.CheckSignature(4, "ZSI\x09");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public GameVersion Version;
public enum GameVersion
{
OOT3D,
MM3D,
}
public enum HeaderCommands : uint
{
Actor = 0x01,
Collision = 0x03,
Rooms = 0x04,
Mesh = 0x0A,
DoorActor = 0x0E,
SkyboxSettings = 0x11,
End = 0x14,
MultiSetup = 0x18,
EnvironmentSettings = 0x0F,
}
public void Load(System.IO.Stream stream)
{
Text = FileName;
using (var reader = new FileReader(stream))
{
reader.ByteOrder = Syroot.BinaryData.ByteOrder.LittleEndian;
string Signature = reader.ReadString(4, Encoding.ASCII);
switch (Signature)
{
case "ZSI\x01":
Version = GameVersion.OOT3D;
break;
default:
Version = GameVersion.MM3D;
break;
}
string CodeName = reader.ReadString(0x0C);
ReadScene(reader);
}
}
private void ReadScene(FileReader reader)
{
while (true)
{
reader.SetByteOrder(true);
uint cmd1 = reader.ReadUInt32();
reader.SetByteOrder(false);
uint cmd2 = reader.ReadUInt32();
reader.Seek(0x08);
var cmdType = cmd1 >> 24;
if (cmdType == (uint)HeaderCommands.End)
break;
switch (cmdType)
{
case (uint)HeaderCommands.EnvironmentSettings:
{
Nodes.Add("EnvironmentSettings");
}
break;
case (uint)HeaderCommands.DoorActor:
{
Nodes.Add("DoorActor");
}
break;
case (uint)HeaderCommands.Rooms:
{
Nodes.Add("Rooms");
}
break;
case (uint)HeaderCommands.SkyboxSettings:
{
Nodes.Add("SkyboxSettings");
}
break;
}
}
}
public void Unload()
{
}
public byte[] Save()
{
return null;
}
}
}

View File

@ -57,8 +57,8 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
public LM2_Renderer Renderer;
public DrawableContainer DrawableContainer = new DrawableContainer();
TreeNode textureFolder = new TreeNode("Textures");
TreeNode modelFolder = new TreeNode("Models");
TextureFolder textureFolder = new TextureFolder("Textures");
LM2_ModelFolder modelFolder;
TreeNode materialNamesFolder = new TreeNode("Material Names");
TreeNode chunkFolder = new TreeNode("Chunks");
@ -70,6 +70,7 @@ namespace FirstPlugin.LuigisMansion.DarkMoon
public bool DrawablesLoaded = false;
public void Load(System.IO.Stream stream)
{
modelFolder = new LM2_ModelFolder(this);
DrawableContainer.Name = FileName;
Renderer = new LM2_Renderer();
DrawableContainer.Drawables.Add(Renderer);

View File

@ -163,73 +163,44 @@ namespace FirstPlugin
}
}
public int GetTotalCount()
{
int count = 0;
foreach (var dir in Nodes)
GetTotalCount(dir, count);
return count;
}
private List<FileEntry> _savedFiles = new List<FileEntry>();
private List<DirectoryEntry> _savedDirectories = new List<DirectoryEntry>();
public int GetFileCount()
private void LoadAllDirectoriesAndFiles(DirectoryEntry parentDir)
{
int count = 0;
foreach (var dir in Nodes)
GetFileCount(dir, count);
return count;
}
public int GetDirectoryCount()
{
int count = 0;
foreach (var dir in Nodes)
GetDirectoryCount(dir, count);
return count;
}
private int GetTotalCount(INode node, int count)
{
count++;
if (node is DirectoryEntry)
for (int i = 0; i < parentDir.nodes.Count; i++)
{
foreach (var c in ((DirectoryEntry)node).nodes)
return GetTotalCount(c, count);
if (parentDir.nodes[i] is DirectoryEntry)
{
_savedDirectories.Add((DirectoryEntry)parentDir.nodes[i]);
}
else
_savedFiles.Add((FileEntry)parentDir.nodes[i]);
}
return count;
}
private int GetFileCount(INode node, int count)
{
if (node is FileEntry)
count++;
if (node is DirectoryEntry)
for (int i = 0; i < parentDir.nodes.Count; i++)
{
foreach (var c in ((DirectoryEntry)node).nodes)
return GetFileCount(c, count);
if (parentDir.nodes[i] is DirectoryEntry)
LoadAllDirectoriesAndFiles((DirectoryEntry)parentDir.nodes[i]);
}
return count;
}
private int GetDirectoryCount(INode node, int count)
{
if (node is DirectoryEntry)
{
count++;
foreach (var c in ((DirectoryEntry)node).nodes)
return GetDirectoryCount(c, count);
}
return count;
}
//Save a string table to a char array like WArchive
//It's a good idea, and i don't want to deal with offset linking
private List<char> _exportStringTable;
private List<byte[]> _savedFileData;
public void SaveFile(FileWriter writer)
{
_exportStringTable = new List<char>();
_savedFileData = new List<byte[]>();
_savedDirectories.Add(Directories[0]);
LoadAllDirectoriesAndFiles(Directories[0]);
_exportStringTable = new List<char>();
_exportStringTable.AddRange(".\0".ToCharArray());
_exportStringTable.AddRange("..\0".ToCharArray());
long pos = writer.Position;
writer.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;
@ -244,40 +215,126 @@ namespace FirstPlugin
writer.SeekBegin(HeaderSize);
long InfoPos = writer.Position;
writer.Write(GetDirectoryCount());
writer.Write(_savedDirectories.Count);
writer.Write(uint.MaxValue); //DirectoryOffset
writer.Write(GetFileCount());
writer.Write(_savedDirectories.Count + _savedFiles.Count);
writer.Write(uint.MaxValue); //File Node Offset
writer.Write(uint.MaxValue); //String pool size
writer.Write(uint.MaxValue); //String pool offset
writer.Write((ushort)GetFileCount());
writer.Write((ushort)0);
writer.Write((ushort)Unknown);
writer.Write(0); //padding
//Write directory Offset
WriteOffset(writer, 4, InfoPos);
for (int dir = 0; dir < Directories.Length; dir++)
for (int dir = 0; dir < _savedDirectories.Count; dir++)
{
Directories[dir].Write(writer);
writer.Write(_savedDirectories[dir].Identifier);
writer.Write((int)_exportStringTable.Count);
writer.Write(_savedDirectories[dir].Hash);
writer.Write((ushort)(_savedDirectories[dir].nodes.Count));
// writer.Write(_savedDirectories[dir].FirstNodeIndex);
writer.Write(_savedFiles.FindIndex(i => i.Name == _savedDirectories[dir].nodes[0].Name));
_exportStringTable.AddRange(_savedDirectories[dir].Name.ToCharArray());
_exportStringTable.Add('\0'); //Null terminated
}
writer.Seek(16); //Add padding after directories
writer.Align(32);
//Write the node offset
//Write the files
WriteOffset(writer, 12, InfoPos);
for (int dir = 0; dir < Directories.Length; dir++)
foreach (FileEntry entry in _savedFiles)
{
for (int n = 0; n < Directories[dir].NodeCount; n++)
{
entry.SaveFileFormat();
writer.Write(entry.FileId);
writer.Write(entry.Hash);
writer.Write(entry.Flags);
writer.Seek(1); //Padding
//I'm not sure what each dot does, but handle these based on
//https://github.com/LordNed/WArchive-Tools/blob/master/ArchiveToolsLib/Archive/ArchivePacker.cs#L122
if ((entry.Name == "."))
{
writer.Write((ushort)0);
}
else if ((entry.Name == ".."))
{
writer.Write((ushort)2);
}
else
{
if (_savedFiles.Find(i => i.Name == entry.Name) != null)
{
string test = new string(_exportStringTable.ToArray());
int testt = test.IndexOf(entry.Name);
writer.Write((ushort)test.IndexOf(entry.Name));
}
else
{
// Offset of name in the string table
writer.Write((ushort)_exportStringTable.Count);
// Add name to string table
_exportStringTable.AddRange(entry.Name.ToCharArray());
// Strings must be null terminated
_exportStringTable.Add('\0');
}
}
if (entry.Flags == 0x02)
{
if (entry.FileData[0] != byte.MaxValue)
{
writer.Write((int)entry.FileData[0]);
}
else
{
writer.Write((int)-1);
}
writer.Write((int)0x10); //Fixed data size
}
if (entry.Flags == 0x11)
{
writer.Write((int)_savedFileData.Count);
writer.Write(_savedFileData.Count);
writer.Write(entry.FileData.Length);
_savedFileData.Add(entry.FileData);
}
writer.Write(0);
}
//Write file size
writer.Align(32);
WriteOffset(writer, 20, InfoPos);
writer.Write(_exportStringTable.ToArray());
writer.Align(32);
WriteOffset(writer, 12, pos);
foreach (var data in _savedFileData)
writer.Write(data);
writer.Align(32);
//Write string table size
using (writer.TemporarySeek(pos + 0x4, System.IO.SeekOrigin.Begin))
{
writer.Write((uint)writer.BaseStream.Length);
}
//Write file size
using (writer.TemporarySeek(InfoPos + 16, System.IO.SeekOrigin.Begin))
{
writer.Write((uint)_exportStringTable.Count);
}
}
private void WriteDirectories()
@ -323,15 +380,10 @@ namespace FirstPlugin
public RARC ParentArchive { get; }
public string Name { get; set; }
private uint Identifier;
public uint Identifier;
internal uint NameOffset; //Relative to string table
public ushort Hash { get; set; }
public ushort NodeCount;
public uint FirstNodeIndex { get; set; }
public DirectoryEntry(RARC rarc) { ParentArchive = rarc; }
@ -344,8 +396,6 @@ namespace FirstPlugin
nodes.Add(node);
}
internal long _positionPtr;
public void Read(FileReader reader)
{
Identifier = reader.ReadUInt32();
@ -355,17 +405,8 @@ namespace FirstPlugin
FirstNodeIndex = reader.ReadUInt32();
}
public void Write(FileWriter writer)
{
_positionPtr = writer.Position;
public void UpdateHash() {
Hash = CalculateHash(Name);
writer.Write(Identifier);
writer.Write(NameOffset);
writer.Write(Hash);
writer.Write(NodeCount);
writer.Write(FirstNodeIndex);
}
}
@ -416,21 +457,6 @@ namespace FirstPlugin
Offset = reader.ReadUInt32();
Size = reader.ReadUInt32();
}
public void Write(FileWriter writer)
{
_positionPtr = writer.Position;
SaveFileFormat();
writer.Write(FileId);
writer.Write(Hash);
writer.Write(Flags);
writer.Seek(1); //Padding
writer.Write(NameOffset);
writer.Write(uint.MaxValue);
writer.Write(FileData.Length);
}
}
}
}

View File

@ -137,6 +137,9 @@ namespace FirstPlugin
}
sarcData.Files.Clear();
// stream.Close();
// stream.Dispose();
}
public bool AddFile(ArchiveFileInfo archiveFileInfo)

View File

@ -19,7 +19,7 @@ namespace FirstPlugin
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "BCRES" };
public string[] Extension { get; set; } = new string[] { "*.bcres" };
public string[] Extension { get; set; } = new string[] { "*.bcres", "*.cgfx" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }

View File

@ -241,9 +241,12 @@ namespace FirstPlugin
if (FaceGroup.SkinnningMode == SkinnningMode.Rigid)
{
Matrix4 sb = skeleton.bones[(int)FaceGroup.BoneIndexList[v.boneIds[0]]].Transform;
v.pos = Vector3.TransformPosition(v.pos, sb);
v.nrm = Vector3.TransformNormal(v.nrm, sb);
if (v.boneIds.Count > 0)
{
Matrix4 sb = skeleton.bones[(int)FaceGroup.BoneIndexList[v.boneIds[0]]].Transform;
v.pos = Vector3.TransformPosition(v.pos, sb);
v.nrm = Vector3.TransformNormal(v.nrm, sb);
}
}
if (FaceGroup.SkinnningMode == SkinnningMode.None)
{

View File

@ -0,0 +1,243 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Toolbox;
using System.Windows.Forms;
using Toolbox.Library;
using Toolbox.Library.IO;
using Toolbox.Library.Forms;
namespace FirstPlugin
{
public class CTXB : TreeNodeFile, IFileFormat
{
public FileType FileType { get; set; } = FileType.Archive;
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "CTXB" };
public string[] Extension { get; set; } = new string[] { "*.ctxb" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Toolbox.Library.IO.FileReader(stream, true))
{
return reader.CheckSignature(4, "ctxb");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public Header header;
public void Load(System.IO.Stream stream)
{
Text = FileName;
header = new Header();
header.Read(new FileReader(stream), this);
}
public void Unload()
{
}
public byte[] Save()
{
return null;
}
public class Header
{
public List<Chunk> Chunks = new List<Chunk>();
public void Read(FileReader reader, CTXB ctxb)
{
string Magic = reader.ReadSignature(4, "ctxb");
uint FileSize = reader.ReadUInt32();
uint ChunkCount = reader.ReadUInt32();
reader.ReadUInt32(); //padding
uint ChunkOffset = reader.ReadUInt32();
uint TextureDataOffset = reader.ReadUInt32();
for (int i = 0; i < ChunkCount; i++)
Chunks.Add(new Chunk(reader));
for (int i = 0; i < ChunkCount; i++)
{
for (int t = 0; t < Chunks[i].Textures.Count; t++)
{
var texWrapper = new TextureWrapper();
texWrapper.Text = $"Texture {t}";
texWrapper.ImageKey = "texture";
texWrapper.SelectedImageKey = texWrapper.ImageKey;
if (Chunks[i].Textures[t].Name != string.Empty)
texWrapper.Text = Chunks[i].Textures[t].Name;
texWrapper.Width = Chunks[i].Textures[t].Width;
texWrapper.Height = Chunks[i].Textures[t].Height;
texWrapper.Format = CTR_3DS.ConvertPICAToGenericFormat(Chunks[i].Textures[t].PicaFormat);
reader.SeekBegin(TextureDataOffset + Chunks[i].Textures[t].DataOffset);
texWrapper.ImageData = reader.ReadBytes((int)Chunks[i].Textures[t].ImageSize);
ctxb.Nodes.Add(texWrapper);
}
}
}
public class Chunk
{
public readonly string Magic = "tex ";
public List<Texture> Textures = new List<Texture>();
public Chunk(FileReader reader)
{
reader.ReadSignature(4, Magic);
uint SectionSize = reader.ReadUInt32();
uint TextureCount = reader.ReadUInt32();
for (int i = 0; i < TextureCount; i++)
Textures.Add(new Texture(reader));
}
}
public class Texture
{
public ushort MaxLevel { get; set; }
public ushort Unknown { get; set; }
public ushort Width { get; set; }
public ushort Height { get; set; }
public string Name { get; set; }
public uint ImageSize { get; set; }
public uint DataOffset { get; set; }
public CTR_3DS.PICASurfaceFormat PicaFormat;
public enum TextureFormat : uint
{
ETC1 = 0x0000675A,
ETC1A4 = 0x0000675B,
RGBA8 = 0x14016752,
RGBA4444 = 0x80336752,
RGBA5551 = 0x80346752,
RGB565 = 0x83636754,
RGB8 = 0x14016754,
A8 = 0x14016756,
L8 = 0x14016757,
L4 = 0x67616757,
LA8 = 0x14016758,
}
public Texture(FileReader reader)
{
ImageSize = reader.ReadUInt32();
MaxLevel = reader.ReadUInt16();
Unknown = reader.ReadUInt16();
Width = reader.ReadUInt16();
Height = reader.ReadUInt16();
TextureFormat Format = reader.ReadEnum<TextureFormat>(true);
DataOffset = reader.ReadUInt32();
Name = reader.LoadString(false, typeof(uint));
PicaFormat = ToPica(Format);
}
private static CTR_3DS.PICASurfaceFormat ToPica(TextureFormat format)
{
switch (format)
{
case TextureFormat.A8: return CTR_3DS.PICASurfaceFormat.A8;
case TextureFormat.ETC1: return CTR_3DS.PICASurfaceFormat.ETC1;
case TextureFormat.ETC1A4: return CTR_3DS.PICASurfaceFormat.ETC1A4;
case TextureFormat.L4: return CTR_3DS.PICASurfaceFormat.L4;
case TextureFormat.L8: return CTR_3DS.PICASurfaceFormat.L8;
case TextureFormat.LA8: return CTR_3DS.PICASurfaceFormat.LA8;
case TextureFormat.RGB565: return CTR_3DS.PICASurfaceFormat.RGB565;
case TextureFormat.RGBA4444: return CTR_3DS.PICASurfaceFormat.RGBA4;
case TextureFormat.RGBA5551: return CTR_3DS.PICASurfaceFormat.RGBA5551;
case TextureFormat.RGBA8: return CTR_3DS.PICASurfaceFormat.RGBA8;
case TextureFormat.RGB8: return CTR_3DS.PICASurfaceFormat.RGB8;
default:
throw new Exception($"Unsupported format! {format}");
}
}
}
public class TextureWrapper : STGenericTexture
{
public byte[] ImageData;
public override bool CanEdit { get; set; } = false;
public override TEX_FORMAT[] SupportedFormats
{
get
{
return new TEX_FORMAT[]
{
TEX_FORMAT.B5G6R5_UNORM,
TEX_FORMAT.R8G8_UNORM,
TEX_FORMAT.B5G5R5A1_UNORM,
TEX_FORMAT.B4G4R4A4_UNORM,
TEX_FORMAT.LA8,
TEX_FORMAT.HIL08,
TEX_FORMAT.L8,
TEX_FORMAT.A8_UNORM,
TEX_FORMAT.LA4,
TEX_FORMAT.A4,
TEX_FORMAT.ETC1_UNORM,
TEX_FORMAT.ETC1_A4,
};
}
}
public TextureWrapper() {
PlatformSwizzle = PlatformSwizzle.Platform_3DS;
}
public override void OnClick(TreeView treeview)
{
UpdateEditor();
}
private void UpdateEditor()
{
ImageEditorBase editor = (ImageEditorBase)LibraryGUI.GetActiveContent(typeof(ImageEditorBase));
if (editor == null)
{
editor = new ImageEditorBase();
editor.Dock = DockStyle.Fill;
LibraryGUI.LoadEditor(editor);
}
editor.Text = Text;
editor.LoadProperties(GenericProperties);
editor.LoadImage(this);
}
public override void SetImageData(System.Drawing.Bitmap bitmap, int ArrayLevel)
{
}
public override byte[] GetImageData(int ArrayLevel = 0, int MipLevel = 0)
{
return ImageData;
}
}
}
}
}

View File

@ -225,6 +225,8 @@
<Compile Include="FileFormats\Archives\Sonic Racing\SP2.cs" />
<Compile Include="FileFormats\Archives\TMPK.cs" />
<Compile Include="FileFormats\Archives\U8.cs" />
<Compile Include="FileFormats\Archives\Grezzo\ZAR.cs" />
<Compile Include="FileFormats\Archives\Grezzo\ZSI.cs" />
<Compile Include="FileFormats\Audio\Archives\BARS.cs" />
<Compile Include="FileFormats\Audio\BARSLIST.cs" />
<Compile Include="FileFormats\Audio\BCSTM.cs" />
@ -267,6 +269,7 @@
<Compile Include="FileFormats\Font\BffntCharSet2Xlor.cs" />
<Compile Include="FileFormats\Font\BFTTF.cs" />
<Compile Include="FileFormats\Message\MSBP.cs" />
<Compile Include="FileFormats\Texture\CTXB.cs" />
<Compile Include="FileFormats\Texture\TPL.cs" />
<Compile Include="FileFormats\Rom\GCDisk.cs" />
<Compile Include="GL\BMD_Renderer.cs" />

View File

@ -358,8 +358,12 @@ namespace FirstPlugin
Formats.Add(typeof(BFTTF));
Formats.Add(typeof(PACx30XL));
Formats.Add(typeof(BinGzArchive));
// Formats.Add(typeof(MSBP));
// Formats.Add(typeof(MSBP));
Formats.Add(typeof(ZAR));
// Formats.Add(typeof(ZSI));
Formats.Add(typeof(CTXB));
// Formats.Add(typeof(GFA));
//Unfinished wip formats not ready for use

View File

@ -0,0 +1,93 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.IO.Compression;
using System.Threading.Tasks;
using Toolbox.Library.IO;
using K4os.Compression.LZ4.Streams;
namespace Toolbox.Library
{
//From https://github.com/xdanieldzd/N3DSCmbViewer/blob/3c3f66cf40d9122f8d0ebeab07c4db659b426b8b/N3DSCmbViewer/LZSS.cs
//and https://github.com/lue/MM3D/blob/master/src/lzs.cpp
public class LZSS : ICompressionFormat
{
public string[] Description { get; set; } = new string[] { "LZSS Compression" };
public string[] Extension { get; set; } = new string[] { "*.lzs", "*.lzss" };
public bool Identify(Stream stream)
{
using (var reader = new FileReader(stream, true))
{
return reader.CheckSignature(4, "LzS\x01");
}
}
public bool CanCompress { get; } = true;
public Stream Decompress(Stream stream)
{
byte[] arcdata = stream.ToArray();
string tag = Encoding.ASCII.GetString(arcdata, 0, 4);
uint unknown = BitConverter.ToUInt32(arcdata, 4);
uint decompressedSize = BitConverter.ToUInt32(arcdata, 8);
uint compressedSize = BitConverter.ToUInt32(arcdata, 12);
if (arcdata.Length != compressedSize + 0x10) throw new Exception("compressed size mismatch");
List<byte> outdata = new List<byte>();
byte[] BUFFER = new byte[4096];
for (int i = 0; i < BUFFER.Length; i++) BUFFER[i] = 0;
byte flags8 = 0;
ushort writeidx = 0xFEE;
ushort readidx = 0;
uint fidx = 0x10;
while (fidx < arcdata.Length)
{
flags8 = arcdata[fidx];
fidx++;
for (int i = 0; i < 8; i++)
{
if ((flags8 & 1) != 0)
{
outdata.Add(arcdata[fidx]);
BUFFER[writeidx] = arcdata[fidx];
writeidx++; writeidx %= 4096;
fidx++;
}
else
{
readidx = arcdata[fidx];
fidx++;
readidx |= (ushort)((arcdata[fidx] & 0xF0) << 4);
for (int j = 0; j < (arcdata[fidx] & 0x0F) + 3; j++)
{
outdata.Add(BUFFER[readidx]);
BUFFER[writeidx] = BUFFER[readidx];
readidx++; readidx %= 4096;
writeidx++; writeidx %= 4096;
}
fidx++;
}
flags8 >>= 1;
if (fidx >= arcdata.Length) break;
}
}
if (decompressedSize != outdata.Count)
throw new Exception(string.Format("Size mismatch: got {0} bytes after decompression, expected {1}.\n", outdata.Count, decompressedSize));
return new MemoryStream(outdata.ToArray());
}
public Stream Compress(Stream stream)
{
var mem = new MemoryStream();
return stream;
}
}
}

View File

@ -23,7 +23,7 @@ namespace Toolbox.Library
public static Type[] GetCompressionFormats()
{
List<Type> Formats = new List<Type>();
Formats.Add(typeof(LZSS));
return Formats.ToArray();
}
}

View File

@ -231,7 +231,7 @@ namespace Toolbox.Library.IO
if (OffsetType == typeof(int))
offset = ReadInt32();
if (offset == 0) return null;
if (offset == 0) return string.Empty;
if (IsRelative)
offset = offset + pos;
@ -261,11 +261,19 @@ namespace Toolbox.Library.IO
}
return output.ToArray();
}
public byte[] getSection(uint offset, uint size)
{
Position = offset;
return ReadBytes((int)size);
}
public byte[] getSection(int offset, int size)
{
Position = offset;
return ReadBytes(size);
}
public Vector4 ReadVec4()
{
return new Vector4(ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle());

View File

@ -209,6 +209,7 @@
<Compile Include="Collections\SortExtensions.cs" />
<Compile Include="Compression\LZ4F.cs" />
<Compile Include="Compression\LZ77_WII.cs" />
<Compile Include="Compression\LZSS.cs" />
<Compile Include="Compression\STLibraryCompression.cs" />
<Compile Include="Compression\YAZ0.cs" />
<Compile Include="Compression\ZCMP.cs" />

View File

@ -210,6 +210,16 @@ namespace Toolbox.Library
}
}
//Get compression formats
foreach (ICompressionFormat f in FileManager.GetCompressionFormats())
{
for (int i = 0; i < f.Extension.Length; i++)
{
Filter += $"{f.Extension[i]};";
FilterEach.Add($"{f.Description[0]} ({f.Extension[i]}) |{f.Extension[i]}|");
}
}
Filter += $"{"*.z"};";
Filter += $"{"*.cmp"};";
Filter += $"{"*.yaz0"};";
@ -264,6 +274,17 @@ namespace Toolbox.Library
FilterEach.Add($"{f.Description[0]} ({f.Extension[i]}) |{f.Extension[i]}|");
}
}
//Get compression formats
foreach (ICompressionFormat f in FileManager.GetCompressionFormats())
{
for (int i = 0; i < f.Extension.Length; i++)
{
Filter += $"{f.Extension[i]};";
FilterEach.Add($"{f.Description[0]} ({f.Extension[i]}) |{f.Extension[i]}|");
}
}
Filter += $"{"*.z"};";
Filter += $"{"*.cmp"};";
Filter += $"{"*.yaz0"};";

Binary file not shown.

Binary file not shown.