mirror of
https://github.com/SabreTools/SabreTools.Serialization.git
synced 2026-07-08 18:06:41 +00:00
155 lines
7.7 KiB
C#
155 lines
7.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using SabreTools.Data.Models.OperaFS;
|
|
using SabreTools.Text.Extensions;
|
|
|
|
namespace SabreTools.Wrappers
|
|
{
|
|
public partial class OperaFS : IPrintable
|
|
{
|
|
#if NETCOREAPP
|
|
/// <inheritdoc/>
|
|
public string ExportJSON() => System.Text.Json.JsonSerializer.Serialize(Model, _jsonSerializerOptions);
|
|
#else
|
|
/// <inheritdoc/>
|
|
public string ExportJSON() => Newtonsoft.Json.JsonConvert.SerializeObject(Model, _jsonSerializerOptions);
|
|
#endif
|
|
|
|
/// <summary>
|
|
/// Map of printed directories to their sector offset
|
|
/// </summary>
|
|
private readonly Dictionary<DirectoryDescriptor, uint> printedDirectories = [];
|
|
|
|
/// <inheritdoc/>
|
|
public void PrintInformation(StringBuilder builder)
|
|
{
|
|
builder.AppendLine("3DO / M2 (Opera) Filesystem Information:");
|
|
builder.AppendLine("-------------------------");
|
|
builder.AppendLine();
|
|
|
|
Print(builder, VolumeDescriptor);
|
|
foreach (var kvp in Directories)
|
|
{
|
|
if (printedDirectories.ContainsKey(kvp.Value))
|
|
{
|
|
builder.AppendLine($" Directory Descriptor (Sector {kvp.Key}):");
|
|
builder.AppendLine(" -------------------------");
|
|
builder.AppendLine($" Duplicate of Descriptor at Sector {printedDirectories[kvp.Value]}");
|
|
builder.AppendLine();
|
|
continue;
|
|
}
|
|
|
|
Print(builder, kvp.Key, kvp.Value);
|
|
printedDirectories.Add(kvp.Value, kvp.Key);
|
|
}
|
|
}
|
|
|
|
internal static void Print(StringBuilder builder, VolumeDescriptor vd)
|
|
{
|
|
builder.AppendLine(" Volume Descriptor:");
|
|
builder.AppendLine(" -------------------------");
|
|
|
|
builder.AppendLine(vd.RecordType, " Record Type");
|
|
builder.AppendLine(vd.VolumeSyncBytes, " Volume Sync Bytes");
|
|
builder.AppendLine(vd.StructureVersion, " Structure Version");
|
|
|
|
builder.AppendLine((byte)vd.VolumeFlags, " Volume Flags");
|
|
if (vd.VolumeFlags != 0)
|
|
{
|
|
builder.AppendLine(" Volume Flags (Parsed)");
|
|
builder.AppendLine((vd.VolumeFlags & VolumeFlags.M2) == VolumeFlags.M2, " M2 Disc (or M1 Data Disc)");
|
|
builder.AppendLine((vd.VolumeFlags & VolumeFlags.M2_ONLY) == VolumeFlags.M2_ONLY, " M2 Only");
|
|
builder.AppendLine((vd.VolumeFlags & VolumeFlags.M2_DATA_DISC) == VolumeFlags.M2_DATA_DISC, " M2 Data Disc");
|
|
builder.AppendLine((vd.VolumeFlags & VolumeFlags.M2_SIGNED) == VolumeFlags.M2_SIGNED, " M2 Signed");
|
|
builder.AppendLine((vd.VolumeFlags & VolumeFlags.RESERVED_MASK) != 0, " Reserved Bits Set");
|
|
}
|
|
|
|
builder.AppendLine(Encoding.UTF8.GetString(vd.VolumeCommentary), " Volume Commentary");
|
|
builder.AppendLine(Encoding.UTF8.GetString(vd.VolumeIdentifier), " Volume Identifier");
|
|
builder.AppendLine(vd.VolumeUniqueIdentifier, " Volume Unique Identifier");
|
|
builder.AppendLine(vd.VolumeBlockSize, " Volume Block Size");
|
|
builder.AppendLine(vd.VolumeBlockCount, " Volume Block Count");
|
|
builder.AppendLine(vd.RootUniqueIdentifier, " Root Unique Identifier");
|
|
builder.AppendLine(vd.RootDirectoryBlockCount, " Root Directory Block Count");
|
|
builder.AppendLine(vd.RootDirectoryBlockSize, " Root Directory Block Size");
|
|
builder.AppendLine(vd.RootDirectoryLastAvatarIndex, " Root Directory Last Avatar Index");
|
|
builder.AppendLine(vd.RootDirectoryAvatarList, " Root Directory Avatar List");
|
|
|
|
if ((vd.VolumeFlags & VolumeFlags.M2) == VolumeFlags.M2)
|
|
{
|
|
builder.AppendLine(vd.RomTagCount, " Rom Tag Count");
|
|
builder.AppendLine(vd.ApplicationID, " Application ID");
|
|
if (vd.Reserved is null)
|
|
builder.AppendLine(vd.Reserved, " Reserved Bytes");
|
|
else if (Array.TrueForAll(vd.Reserved, b => b == 0))
|
|
builder.AppendLine($"Zeroed", " Reserved Bytes");
|
|
else
|
|
builder.AppendLine($"Not Zeroed", " Reserved Bytes");
|
|
}
|
|
|
|
int offset = Array.IndexOf(Constants.PaddingBytes, vd.Padding[0]);
|
|
int index = 0;
|
|
bool isDuck = (offset >= 0) && Array.TrueForAll(vd.Padding, b => b == Constants.PaddingBytes[(index++ + offset) % Constants.PaddingBytes.Length]);
|
|
if (isDuck)
|
|
builder.AppendLine("Expected data (iamaduck)", " Padding");
|
|
else
|
|
builder.AppendLine("Unexpected data", " Padding");
|
|
|
|
builder.AppendLine();
|
|
}
|
|
|
|
internal static void Print(StringBuilder builder, uint sector, DirectoryDescriptor dir)
|
|
{
|
|
builder.AppendLine($" Directory Descriptor (Sector {sector}):");
|
|
builder.AppendLine(" -------------------------");
|
|
|
|
builder.AppendLine(dir.NextBlock, " Next Block");
|
|
builder.AppendLine(dir.PreviousBlock, " Previous Block");
|
|
builder.AppendLine(dir.Flags, " Flags");
|
|
builder.AppendLine(dir.FirstFreeByte, " First Free Byte");
|
|
builder.AppendLine(dir.FirstEntryOffset, " First Entry Offset");
|
|
|
|
foreach (var dr in dir.DirectoryRecords)
|
|
{
|
|
Print(builder, dr);
|
|
}
|
|
|
|
builder.AppendLine();
|
|
}
|
|
|
|
internal static void Print(StringBuilder builder, DirectoryRecord dr)
|
|
{
|
|
builder.AppendLine(" Directory Record:");
|
|
builder.AppendLine(" -------------------------");
|
|
|
|
builder.AppendLine((byte)dr.DirectoryRecordFlags, " Directory Record Flags");
|
|
if ((byte)dr.DirectoryRecordFlags != 0)
|
|
{
|
|
builder.AppendLine(" Directory Record Flags (Parsed)");
|
|
builder.AppendLine((dr.DirectoryRecordFlags & DirectoryRecordFlags.DIRECTORY) == DirectoryRecordFlags.DIRECTORY, " Directory");
|
|
builder.AppendLine((dr.DirectoryRecordFlags & DirectoryRecordFlags.READ_ONLY) == DirectoryRecordFlags.READ_ONLY, " Read-only");
|
|
builder.AppendLine((dr.DirectoryRecordFlags & DirectoryRecordFlags.SYSTEM) == DirectoryRecordFlags.SYSTEM, " Filesystem Use");
|
|
builder.AppendLine((dr.DirectoryRecordFlags & DirectoryRecordFlags.BLOCK_FINAL) == DirectoryRecordFlags.BLOCK_FINAL, " Final in Block");
|
|
builder.AppendLine((dr.DirectoryRecordFlags & DirectoryRecordFlags.DIRECTORY_FINAL) == DirectoryRecordFlags.DIRECTORY_FINAL, " Final in Directory");
|
|
builder.AppendLine((dr.DirectoryRecordFlags & DirectoryRecordFlags.RESERVED_MASK) != 0, " Reserved Bits Set");
|
|
}
|
|
|
|
builder.AppendLine(dr.UniqueIdentifier, " Unique Identifier");
|
|
builder.AppendLine(dr.Type, " Type");
|
|
builder.AppendLine(Encoding.UTF8.GetString(dr.Type), " Type (Parsed)");
|
|
builder.AppendLine(dr.BlockSize, " BlockSize");
|
|
builder.AppendLine(dr.ByteCount, " ByteCount");
|
|
builder.AppendLine(dr.BlockCount, " BlockCount");
|
|
builder.AppendLine(dr.Burst, " Burst");
|
|
builder.AppendLine(dr.Gap, " Gap");
|
|
builder.AppendLine(dr.Filename, " Filename");
|
|
builder.AppendLine(Encoding.UTF8.GetString(dr.Filename), " Filename (Parsed)");
|
|
builder.AppendLine(dr.LastAvatarIndex, " LastAvatarIndex");
|
|
builder.AppendLine(dr.AvatarList, " AvatarList");
|
|
|
|
builder.AppendLine();
|
|
}
|
|
}
|
|
}
|