extended the XNB file format (without breaking compatibility) for ANX specific extensions

This commit is contained in:
Glatzemann 2012-08-27 12:19:52 +00:00
parent 64ac2da9dd
commit 778b3c1ee2
8 changed files with 75 additions and 44 deletions

View File

@ -16,14 +16,13 @@ namespace ANX.Framework.Content.Pipeline
public class AnxContentImporterContext : ContentImporterContext public class AnxContentImporterContext : ContentImporterContext
{ {
private string intermediateDirectory; private string intermediateDirectory;
private ContentBuildLogger logger;
private string outputDirectory; private string outputDirectory;
public AnxContentImporterContext(BuildContent buildContent, BuildItem buildItem, ContentBuildLogger logger) public AnxContentImporterContext(BuildContent buildContent, BuildItem buildItem, ContentBuildLogger logger)
: base(logger)
{ {
BuildContent = buildContent; BuildContent = buildContent;
BuildItem = buildItem; BuildItem = buildItem;
this.logger = logger;
} }
public BuildContent BuildContent public BuildContent BuildContent
@ -46,14 +45,6 @@ namespace ANX.Framework.Content.Pipeline
} }
} }
public override ContentBuildLogger Logger
{
get
{
return Logger;
}
}
public override string OutputDirectory public override string OutputDirectory
{ {
get get

View File

@ -14,14 +14,24 @@ namespace ANX.Framework.Content.Pipeline
{ {
public abstract class ContentImporterContext public abstract class ContentImporterContext
{ {
public ContentImporterContext() public ContentImporterContext(ContentBuildLogger logger)
{ {
//TODO: implement if (logger == null)
{
throw new ArgumentNullException("logger");
}
this.Logger = logger;
} }
public abstract string IntermediateDirectory { get; } public abstract string IntermediateDirectory { get; }
public abstract ContentBuildLogger Logger { get; }
public abstract string OutputDirectory { get; } public abstract string OutputDirectory { get; }
public abstract void AddDependency(string filename); public abstract void AddDependency(string filename);
public ContentBuildLogger Logger
{
get;
protected set;
}
} }
} }

View File

@ -13,7 +13,7 @@ using ANX.Framework.Content.Pipeline.Graphics;
namespace ANX.Framework.Content.Pipeline namespace ANX.Framework.Content.Pipeline
{ {
[ContentImporter(".fx")] [ContentImporter(new string[] { ".fx", ".fxg" })]
public class EffectImporter : ContentImporter<EffectContent> public class EffectImporter : ContentImporter<EffectContent>
{ {
public EffectImporter() public EffectImporter()

View File

@ -121,7 +121,7 @@ namespace ANX.Framework.Content.Pipeline.Processors
{ {
if ((debugMode == EffectProcessorDebugMode.Auto && System.Diagnostics.Debugger.IsAttached) || debugMode == EffectProcessorDebugMode.Debug) if ((debugMode == EffectProcessorDebugMode.Auto && System.Diagnostics.Debugger.IsAttached) || debugMode == EffectProcessorDebugMode.Debug)
{ {
return "/Od /Op /Zi"; return "/Od /Op";
} }
else else
{ {

View File

@ -30,7 +30,7 @@ namespace ANX.Framework.Content.Pipeline.Serialization.Compiler
#endregion #endregion
const byte xnbFormatVersion = (byte)5; const byte xnbFormatVersion = (byte)6;
char[] xnbMagicWord = new char[] { 'X', 'N', 'B' }; char[] xnbMagicWord = new char[] { 'X', 'N', 'B' };
internal ContentWriter(ContentCompiler compiler, Stream output, bool compressContent, string rootDirectory, string referenceRelocationPath) internal ContentWriter(ContentCompiler compiler, Stream output, bool compressContent, string rootDirectory, string referenceRelocationPath)
@ -212,8 +212,9 @@ namespace ANX.Framework.Content.Pipeline.Serialization.Compiler
Write(xnbMagicWord); // magic bytes for file recognition - 03 bytes Write(xnbMagicWord); // magic bytes for file recognition - 03 bytes
Write((byte)TargetPlatform); // target platform of content file - 01 byte Write((byte)TargetPlatform); // target platform of content file - 01 byte
Write((byte)xnbFormatVersion); // version of this file - 01 byte Write((byte)xnbFormatVersion); // version of this file - 01 byte
Write(new byte[] { (byte)'A', (byte)'N', (byte)'X' }); // ANX magic word - 03 byte
Write((byte)(TargetProfile == GraphicsProfile.HiDef ? 0x01 : 0x00)); // flags - 01 byte Write((byte)(TargetProfile == GraphicsProfile.HiDef ? 0x01 : 0x00)); // flags - 01 byte
Write((int)header.Length + (int)content.Length + 10); // size of file - 04 byte Write((int)header.Length + (int)content.Length + 13); // size of file - 04 byte
if (compressContent) if (compressContent)
{ {
//TODO: write compressed size //TODO: write compressed size

View File

@ -15,7 +15,7 @@ namespace ANX.Framework.Content
{ {
public sealed class ContentReader : BinaryReader public sealed class ContentReader : BinaryReader
{ {
private int graphicsProfile; private GraphicsProfile graphicsProfile;
private List<Action<object>>[] sharedResourceFixups; private List<Action<object>>[] sharedResourceFixups;
@ -23,13 +23,14 @@ namespace ANX.Framework.Content
public ContentManager ContentManager { get; private set; } public ContentManager ContentManager { get; private set; }
public bool AnxExtensions { get; private set; }
public string AssetName { get; private set; } public string AssetName { get; private set; }
private string assetDirectory; private string assetDirectory;
private ContentReader( private ContentReader(ContentManager contentManager, Stream input, string assetName, GraphicsProfile graphicsProfile, bool anxExtensions)
ContentManager contentManager, Stream input, string assetName, int graphicsProfile)
: base(input) : base(input)
{ {
this.AnxExtensions = anxExtensions;
this.ContentManager = contentManager; this.ContentManager = contentManager;
this.AssetName = assetName; this.AssetName = assetName;
this.graphicsProfile = graphicsProfile; this.graphicsProfile = graphicsProfile;
@ -45,20 +46,23 @@ namespace ANX.Framework.Content
public static ContentReader Create( public static ContentReader Create(
ContentManager contentManager, Stream input, string assetName) ContentManager contentManager, Stream input, string assetName)
{ {
int num; GraphicsProfile profile;
input = ContentReader.ReadXnbHeader(input, assetName, out num); bool anxExtensions;
return new ContentReader(contentManager, input, assetName, num);
input = ContentReader.ReadXnbHeader(input, assetName, out profile, out anxExtensions);
return new ContentReader(contentManager, input, assetName, profile, anxExtensions);
} }
public static T ReadAsset<T>( public static T ReadAsset<T>(ContentManager contentManager, Stream input, string assetName)
ContentManager contentManager, Stream input, string assetName)
{ {
int num; GraphicsProfile profile;
input = ContentReader.ReadXnbHeader(input, assetName, out num); bool anxExtensions;
return new ContentReader(contentManager, input, assetName, num).ReadAsset<T>();
input = ContentReader.ReadXnbHeader(input, assetName, out profile, out anxExtensions);
return new ContentReader(contentManager, input, assetName, profile, anxExtensions).ReadAsset<T>();
} }
private static Stream ReadXnbHeader(Stream input, string assetName, out int graphicsProfile) private static Stream ReadXnbHeader(Stream input, string assetName, out GraphicsProfile graphicsProfile, out bool anxExtensions)
{ {
// read the XNB file information // read the XNB file information
// //
@ -75,6 +79,8 @@ namespace ANX.Framework.Content
// | | | x = Xbox 360 // | | | x = Xbox 360
// |--------|----------------------|-------------------------------- // |--------|----------------------|--------------------------------
// | Byte | XNB format version | 5 = XNA Game Studio 4.0 // | Byte | XNB format version | 5 = XNA Game Studio 4.0
// | | | 6 = future XNA version
// | | | OR anx version if the next three bytes are ANX
// |--------|----------------------|-------------------------------- // |--------|----------------------|--------------------------------
// | Byte | Flag bits | Bit 0x01 = content is for HiDef profile (otherwise Reach) // | Byte | Flag bits | Bit 0x01 = content is for HiDef profile (otherwise Reach)
// | | | Bit 0x80 = asset data is compressed // | | | Bit 0x80 = asset data is compressed
@ -83,6 +89,7 @@ namespace ANX.Framework.Content
// | | | .xnb file as stored on disk (including this header block) // | | | .xnb file as stored on disk (including this header block)
BinaryReader reader = new BinaryReader(input); BinaryReader reader = new BinaryReader(input);
anxExtensions = false;
byte magicX = reader.ReadByte(); byte magicX = reader.ReadByte();
byte magicN = reader.ReadByte(); byte magicN = reader.ReadByte();
@ -109,29 +116,33 @@ namespace ANX.Framework.Content
byte formatVersion = reader.ReadByte(); byte formatVersion = reader.ReadByte();
if (formatVersion != 5) if (formatVersion == 6)
{
byte magicVA = reader.ReadByte(); // A
byte magicVN = reader.ReadByte(); // N
byte magicVX = reader.ReadByte(); // X
if (magicVA != 'A' || magicVN != 'N' || magicVX != 'X')
{
throw new ContentLoadException("Not an ANX.Framework version 1.0 XNB file.");
}
anxExtensions = true;
}
else if (formatVersion != 5)
{ {
throw new ContentLoadException("Not an XNA Game Studio version 4.0 XNB file."); throw new ContentLoadException("Not an XNA Game Studio version 4.0 XNB file.");
} }
byte flags = reader.ReadByte(); byte flags = reader.ReadByte();
if ((flags & 0x01) == 0x01) graphicsProfile = ((flags & 0x01) == 0x01 ? GraphicsProfile.HiDef : GraphicsProfile.Reach);
{
// HiDef Profile
graphicsProfile = 1;
}
else
{
// Reach Profile
graphicsProfile = 0;
}
bool isCompressed = (flags & 0x80) != 0; bool isCompressed = (flags & 0x80) != 0;
int sizeOnDisk = reader.ReadInt32(); int sizeOnDisk = reader.ReadInt32();
if (input.CanSeek && ((sizeOnDisk - 10) > (input.Length - input.Position))) if (input.CanSeek && ((sizeOnDisk - (anxExtensions ? 13 : 10)) > (input.Length - input.Position)))
{ {
throw new ContentLoadException("Bad XNB file size."); throw new ContentLoadException("Bad XNB file size.");
} }

View File

@ -45,6 +45,8 @@ namespace ANX.Tools.XNBInspector
// | | | x = Xbox 360 // | | | x = Xbox 360
// |--------|----------------------|-------------------------------- // |--------|----------------------|--------------------------------
// | Byte | XNB format version | 5 = XNA Game Studio 4.0 // | Byte | XNB format version | 5 = XNA Game Studio 4.0
// | | | 6 = future XNA version
// | | | OR anx version if the next three bytes are ANX
// |--------|----------------------|-------------------------------- // |--------|----------------------|--------------------------------
// | Byte | Flag bits | Bit 0x01 = content is for HiDef profile (otherwise Reach) // | Byte | Flag bits | Bit 0x01 = content is for HiDef profile (otherwise Reach)
// | | | Bit 0x80 = asset data is compressed // | | | Bit 0x80 = asset data is compressed
@ -141,8 +143,24 @@ namespace ANX.Tools.XNBInspector
case 5: case 5:
result.Append(Severity.Success, "5 (XNA Game Studio 4.0)"); result.Append(Severity.Success, "5 (XNA Game Studio 4.0)");
break; break;
case 6:
byte magicVA = reader.ReadByte(); // A
byte magicVN = reader.ReadByte(); // N
byte magicVX = reader.ReadByte(); // X
if (magicVA == 'A' && magicVN == 'N' && magicVX == 'X')
{
result.Append(Severity.Success, "6 with additional magic bytes (ANX.Framework 1.0)");
}
else
{
reader.BaseStream.Seek(-3, SeekOrigin.Current);
result.AppendFormat(Severity.Warning, "{0} (Unknown or non XNA/ANX content)", formatVersion);
}
break;
default: default:
result.AppendFormat(Severity.Warning, "{0} (Unknown or non XNA content)", formatVersion); result.AppendFormat(Severity.Warning, "{0} (Unknown or non XNA/ANX content)", formatVersion);
break; break;
} }
result.AppendLine(); result.AppendLine();

View File

@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.3.1.0")] [assembly: AssemblyVersion("0.3.2.0")]
[assembly: AssemblyFileVersion("0.3.1.0")] [assembly: AssemblyFileVersion("0.3.2.0")]