EveryFileExplorer/3DS/ThemeFile.cs
Gericom 744b3f1b2b BCFNT Viewer and more stuff
- Named some fields for themes
- Added Microsoft.VisualBasic.PowerPacks.VS.dll
2014-11-19 17:33:25 +01:00

496 lines
14 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LibEveryFileExplorer.Files;
using System.Drawing;
using System.IO;
using _3DS.UI;
namespace _3DS
{
public class ThemeFile : FileFormat<ThemeFile.ThemeIdentifier>, IViewable, IWriteable
{
public Color topSolidColor;
public Color bottomSolidColor;
public ThemeFile(byte[] Data)
{
EndianBinaryReader er = new EndianBinaryReader(new MemoryStream(Data), Endianness.LittleEndian);
try
{
header = new ThemeHeader(er);
topHeight = 256;
bottomHeight = 256;
switch (header.topScreenDrawType)
{
case 1://solid color
er.BaseStream.Position = header.topScreenSolidColorDataOffset;//7 bytes here, first 4 is rgba, other 3 unknown (possible overlay colour ??)
Byte r = er.ReadByte();
Byte g = er.ReadByte();
Byte b = er.ReadByte();
Byte a1 = er.ReadByte();//alpha makes the colours appear lighter because the 3ds does blending
topSolidColor = Color.FromArgb(a1, r, g, b);
break;
case 3://texture
switch (header.topScreenFrameType)
{
case 0://tex1
case 3://tex1
topWidth = 1024;
topClampWidth = 1008;
topClampHeight = 240;
break;
case 1://tex0
topWidth = 512;
topClampWidth = 412;
topClampHeight = 240;
break;
}
break;
}
switch (header.bottomScreenDrawType)
{
case 1://solid color
er.BaseStream.Position = header.bottomScreenSolidOrTextureOffset;//7 bytes here, first 4 is rgba, other 3 unknown (possible overlay colour ??)
Byte r = er.ReadByte();
Byte g = er.ReadByte();
Byte b = er.ReadByte();
Byte a1 = er.ReadByte();//alpha makes the colours appear lighter because the 3ds does blending
bottomSolidColor = Color.FromArgb(a1, r, g, b);
break;
case 3://texture
switch (header.bottomScreenFrameType)
{
case 0://tex4
case 3://tex4
bottomWidth = 1024;
bottomClampWidth = 1008;
bottomClampHeight = 240;
break;
case 1://tex2
bottomWidth = 512;
bottomClampWidth = 320;
bottomClampHeight = 240;
break;
case 2://tex3
bottomWidth = 1024;
bottomClampWidth = 960;
bottomClampHeight = 240;
break;
}
break;
}
er.BaseStream.Position = header.topScreenTextureOffset;
topScreenTexture = er.ReadBytes((topHeight * topWidth) * 2);
er.BaseStream.Position = header.bottomScreenSolidOrTextureOffset;
bottomScreenTexture = er.ReadBytes((bottomHeight * bottomWidth) * 2);
er.BaseStream.Position = header.FolderOpenedTexOffset;
openFolderTexture = er.ReadBytes((folderWidth * folderHeight) * 4);
er.BaseStream.Position = header.FolderClosedTexOffset;
closedFolderTexture = er.ReadBytes((folderWidth * folderHeight) * 4);
er.BaseStream.Position = header.iconBorder48pxOffset;
iconBorder48pxTexture = er.ReadBytes((iconBorder48pxWidth * iconBorder48pxHeight) * 4);
er.BaseStream.Position = header.iconBorder24pxOffset;
iconBorder24pxTexture = er.ReadBytes((iconBorder24pxWidth * iconBorder24pxHeight) * 4);
}
finally
{
er.Close();
}
}
public string GetSaveDefaultFileFilter()
{
return "3DS System Menu Theme (body_LZ.bin)|body_LZ.bin";
}
public byte[] Write()
{
MemoryStream m = new MemoryStream();
EndianBinaryWriter er = new EndianBinaryWriter(m, Endianness.LittleEndian);
er.BaseStream.Position = 0xD0;//just after header - normal start of data for theme files
header.topScreenTextureOffset = (uint)er.BaseStream.Position;
er.Write(topScreenTexture, 0, topScreenTexture.Length);
header.bottomScreenSolidOrTextureOffset = (uint)er.BaseStream.Position;
er.Write(bottomScreenTexture, 0, bottomScreenTexture.Length);
header.FolderOpenedTexOffset = (uint)er.BaseStream.Position;
er.Write(openFolderTexture, 0, openFolderTexture.Length);
header.FolderClosedTexOffset = (uint)er.BaseStream.Position;
er.Write(closedFolderTexture, 0, closedFolderTexture.Length);
header.iconBorder48pxOffset = (uint)er.BaseStream.Position;
er.Write(iconBorder48pxTexture, 0, iconBorder48pxTexture.Length);
header.iconBorder24pxOffset = (uint)er.BaseStream.Position;
er.Write(iconBorder24pxTexture, 0, iconBorder24pxTexture.Length);
header.Write(er);
return m.ToArray();
}
public int iconBorder48pxWidth = 64;
public int iconBorder48pxHeight = 128;
public byte[] iconBorder48pxTexture;
public Bitmap GetIconBorder48px(bool clamp)
{
if (clamp)
return GPU.Textures.ToBitmap(iconBorder48pxTexture, 36, 72, GPU.Textures.ImageFormat.RGB8, false);
return GPU.Textures.ToBitmap(iconBorder48pxTexture, iconBorder48pxWidth, iconBorder48pxHeight, GPU.Textures.ImageFormat.RGB8, true);
}
public int iconBorder24pxWidth = 32;
public int iconBorder24pxHeight = 64;
public byte[] iconBorder24pxTexture;
public Bitmap GetIconBorder24px(bool clamp)
{
if (clamp)
return GPU.Textures.ToBitmap(iconBorder24pxTexture, 25, 50, GPU.Textures.ImageFormat.RGB8, false);
return GPU.Textures.ToBitmap(iconBorder24pxTexture, iconBorder24pxWidth, iconBorder24pxHeight, GPU.Textures.ImageFormat.RGB8, true);
}
public int folderWidth = 128;
public int folderHeight = 64;
public byte[] openFolderTexture;
public byte[] closedFolderTexture;
public Bitmap GetOpenFolderTexture(bool clamp)
{
if (clamp)
return GPU.Textures.ToBitmap(openFolderTexture, 82, 64, GPU.Textures.ImageFormat.RGB8, false);
return GPU.Textures.ToBitmap(openFolderTexture, folderWidth, folderHeight, GPU.Textures.ImageFormat.RGB8, true);
}
public Bitmap GetClosedFolderTexture(bool clamp)
{
if (clamp)
return GPU.Textures.ToBitmap(closedFolderTexture, 74, 64, GPU.Textures.ImageFormat.RGB8, false);
return GPU.Textures.ToBitmap(closedFolderTexture, folderWidth, folderHeight, GPU.Textures.ImageFormat.RGB8, true);
}
public int bottomWidth;
public int bottomHeight;
public byte[] bottomScreenTexture;
public int bottomClampWidth;
public int bottomClampHeight;
public Bitmap GetBottomTexture(bool clamp)
{
if (clamp)
return GPU.Textures.ToBitmap(bottomScreenTexture, bottomClampWidth, bottomClampHeight, GPU.Textures.ImageFormat.RGB565, false);
return GPU.Textures.ToBitmap(bottomScreenTexture, bottomWidth, bottomHeight, GPU.Textures.ImageFormat.RGB565, true);
}
public int topWidth;
public int topHeight;
public byte[] topScreenTexture;
public int topClampWidth;
public int topClampHeight;
public Bitmap GetTopTexture(bool clamp)
{
if (clamp)
return GPU.Textures.ToBitmap(topScreenTexture, topClampWidth, topClampHeight, GPU.Textures.ImageFormat.RGB565, false);
return GPU.Textures.ToBitmap(topScreenTexture, topWidth, topHeight, GPU.Textures.ImageFormat.RGB565, true);
}
public System.Windows.Forms.Form GetDialog()
{
return new ThemeViewer(this);
}
public AudioSection audioSection;
public class AudioSection
{
public AudioSection(EndianBinaryReader er)
{
}
}
public ThemeHeader header;
public class ThemeHeader
{
public ThemeHeader(EndianBinaryReader er)
{
//offset 0x0
Version = er.ReadUInt32();
Unknown1 = er.ReadByte();
UseBGMusic = er.ReadByte() == 1;
Padding = er.ReadBytes(6);
//offset 0xC
topScreenDrawType = er.ReadUInt32();// 0 = none, 1 = solid colour, 2 = extension of val1, 3 = texture
topScreenFrameType = er.ReadUInt32();//0 = solid colour(only when draw type is 1 else uses tex 0), 1 = texture0, 3 = texture1
topScreenSolidColorDataOffset = er.ReadUInt32();
topScreenTextureOffset = er.ReadUInt32();
topScreenAdditionalTextureOffset = er.ReadUInt32();//used with draw type val2, optional when using draw type val2
//offset 0x20
bottomScreenDrawType = er.ReadUInt32();
bottomScreenFrameType = er.ReadUInt32();
bottomScreenSolidOrTextureOffset = er.ReadUInt32();
//offset 0x2C
UseSelectorColor = er.ReadUInt32() == 1;
SelectorColorBlockOffset = er.ReadUInt32();//0xC length
//offset 0x34
UseFolderColor = er.ReadUInt32() == 1;
FolderColorBlockOffset = er.ReadUInt32();//0xC length
//offset 0x3C
UseFolderTex = er.ReadUInt32() == 1;
FolderClosedTexOffset = er.ReadUInt32();//texture 6
FolderOpenedTexOffset = er.ReadUInt32();//texture 7
//offset 0x48
useUnknownBlock2 = er.ReadUInt32() == 1;
unknownBlock2Offset = er.ReadUInt32();//0xD length
//offset 0x50
useIconBorders = er.ReadUInt32() == 1;
iconBorder48pxOffset = er.ReadUInt32();
iconBorder24pxOffset = er.ReadUInt32();
//offset 0x4C
useUnknownBlock3 = er.ReadUInt32() == 1;
unknownBlock3Offset = er.ReadUInt32();//0xD length
useUnknownBlock4 = er.ReadUInt32() == 1;
unknownBlock4Offset = er.ReadUInt32();//0x9 length
useUnknownBlock5and6 = er.ReadUInt32() == 1;
unknownBlock5Offset = er.ReadUInt32();//0x20 length
unknownBlock6Offset = er.ReadUInt32();//0x20 length
useUnknownBlock7 = er.ReadUInt32() == 1;
unknownBlock7Offset = er.ReadUInt32();//0xD length
useUnknownBlock8 = er.ReadUInt32() == 1;
unknownBlock8Offset = er.ReadUInt32();//0xD length
useUnknownBlock9 = er.ReadUInt32() == 1;
unknownBlock9Offset = er.ReadUInt32();//0x9 length
useUnknownBlock10 = er.ReadUInt32() == 1;
unknownBlock10Offset = er.ReadUInt32();//0xD length
useUnknownBlock11 = er.ReadUInt32() == 1;
unknownBlock11Offset = er.ReadUInt32();//0x20 length
useUnknownBlock12 = er.ReadUInt32() == 1;
unknownBlock12Offset = er.ReadUInt32();//0x15 length
useUnknownBlock13 = er.ReadUInt32() == 1;
unknownBlock13Offset = er.ReadUInt32();//0xC length
useUnknownBlock14 = er.ReadUInt32() == 1;
unknownBlock14Offset = er.ReadUInt32();//0x6 length
useAudioSection = er.ReadUInt32() == 1;
audioSectionSize = er.ReadUInt32();
audioSectionOffset = er.ReadUInt32();
}
public void Write(EndianBinaryWriter er)
{
er.BaseStream.Position = 0;
//write header data
er.Write(Version);
er.Write(Unknown1);
er.Write((byte)(UseBGMusic ? 1 : 0));
er.Write(Padding, 0, 6);
er.Write(topScreenDrawType);
er.Write(topScreenFrameType);
er.Write(topScreenSolidColorDataOffset);
er.Write(topScreenTextureOffset);
er.Write(topScreenAdditionalTextureOffset);
er.Write(bottomScreenDrawType);
er.Write(bottomScreenFrameType);
er.Write(bottomScreenSolidOrTextureOffset);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write(UseFolderTex ? 1u : 0u);//TODO write 0 instead or somethign when this is disabled?
er.Write(FolderClosedTexOffset);
er.Write(FolderOpenedTexOffset);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write(useIconBorders ? 1u : 0u);//TODO write 0 instead or somethign when this is disabled?
er.Write(iconBorder48pxOffset);
er.Write(iconBorder24pxOffset);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
er.Write((UInt32)0);
}
public UInt32 Version;
public Byte Unknown1;
public bool UseBGMusic;
public Byte[] Padding;//6
public UInt32 topScreenDrawType;
public UInt32 topScreenFrameType;
public UInt32 topScreenSolidColorDataOffset;
public UInt32 topScreenTextureOffset;
public UInt32 topScreenAdditionalTextureOffset;
public UInt32 bottomScreenDrawType;
public UInt32 bottomScreenFrameType;
public UInt32 bottomScreenSolidOrTextureOffset;
public bool UseSelectorColor;
public UInt32 SelectorColorBlockOffset;
public bool UseFolderColor;
public UInt32 FolderColorBlockOffset;
public bool UseFolderTex;//6 and 7
public UInt32 FolderClosedTexOffset;
public UInt32 FolderOpenedTexOffset;
public bool useUnknownBlock2;
public UInt32 unknownBlock2Offset;
public bool useIconBorders;
public UInt32 iconBorder48pxOffset;
public UInt32 iconBorder24pxOffset;
public bool useUnknownBlock3;
public UInt32 unknownBlock3Offset;
public bool useUnknownBlock4;
public UInt32 unknownBlock4Offset;
public bool useUnknownBlock5and6;
public UInt32 unknownBlock5Offset;
public UInt32 unknownBlock6Offset;
public bool useUnknownBlock7;
public UInt32 unknownBlock7Offset;
public bool useUnknownBlock8;
public UInt32 unknownBlock8Offset;
public bool useUnknownBlock9;
public UInt32 unknownBlock9Offset;
public bool useUnknownBlock10;
public UInt32 unknownBlock10Offset;
public bool useUnknownBlock11;
public UInt32 unknownBlock11Offset;
public bool useUnknownBlock12;
public UInt32 unknownBlock12Offset;
public bool useUnknownBlock13;
public UInt32 unknownBlock13Offset;
public bool useUnknownBlock14;
public UInt32 unknownBlock14Offset;
public Boolean useAudioSection;
public UInt32 audioSectionSize;
public UInt32 audioSectionOffset;
}
public class ThemeIdentifier : FileFormatIdentifier
{
public override string GetCategory()
{
return "3DS Themes";
}
public override string GetFileDescription()
{
return "3DS System Menu Theme (body_LZ.bin)";
}
public override string GetFileFilter()
{
return "3DS System Menu Theme (body_LZ.bin)|body_LZ.bin";
}
public override Bitmap GetIcon()
{
return null;
}
public override FormatMatch IsFormat(EFEFile File)
{
if (File.Name.Equals("body_LZ.bin"))
return FormatMatch.Content;
else
return FormatMatch.No;
}
}
}
}