Table of Contents

Class XnbWriter

Namespace
ShadowDusk.Core
Assembly
ShadowDusk.Core.dll

Wraps a compiled effect payload in the XNA/MonoGame XNB content container, so a consumer can drop the file where their mgfxc-built .xnb used to sit and keep calling Content.Load<Effect>("Foo") without changing a line of code (issue #199, Phase 60).

This writer is deliberately only a container. The payload it wraps is the exact .mgfx / .knifx / .fxb ShadowDusk already produces and has render-proven, so no shader-compilation behaviour changes and no existing output byte moves. It is pure managed code with no native dependency, so it runs on every host including WASM and Android.

Byte layout (uncompressed single-effect asset), measured from real dotnet-mgcb 3.8.4.1 output for /platform: Windows, DesktopGL, Android, iOS and MacOSX — not transcribed from documentation:

'X' 'N' 'B'                 magic
<platform>            one of the runtime's accepted identifiers (see PlatformIdentifierFor)
0x05                        format version
0x00                        flags (bit 0x80 = LZX, 0x40 = LZ4; this writer emits uncompressed)
int32                       TOTAL file size, header included
7-bit                       type-reader count (always 1 for an effect)
  7-bit                     reader name length
  bytes                     reader name (EffectReaderTypeName)
  int32                     reader version (0)
7-bit                       shared-resource count (0)
7-bit                       type id of the primary object (1 = 1-based index into the readers)
int32                       payload length
bytes                       the effect payload, verbatim
public static class XnbWriter
Inheritance
XnbWriter
Inherited Members

Fields

EffectReaderTypeName

The type-reader manifest entry for an effect, byte-identical to what mgcb writes.

The embedded assembly version is deliberate and is deliberately ignored by every consumer runtime. All three strip it before resolving the reader, but they do not strip it the same way, and the intersection of their rules is exactly this string:

  • MonoGame (ContentTypeReaderManager.PrepareType) only runs its version-stripping regex when the name contains PublicKeyToken — so the token must be present even though its value is irrelevant.
  • FNA matches one compiled regex requiring the full , <assembly>, Version=…, Culture=…, PublicKeyToken=… triple, and requires the assembly to be one of Microsoft.Xna.Framework[.Graphics|.Video] or MonoGame.Framework. A bare …, MonoGame.Framework with no version does not match, and FNA would then fail to resolve the reader.
  • KNI is a MonoGame fork and consumes stock mgcb output, which is this string.

So the version number here is inert, but the shape around it is load-bearing. Emitting exactly what mgcb emits is the choice that cannot be wrong: every .xnb in every shipped MonoGame game already carries it.

public const string EffectReaderTypeName = "Microsoft.Xna.Framework.Content.EffectReader, MonoGame.Framework, Version=3.8.4.1, Culture=neutral, PublicKeyToken=null"

Field Value

string

FormatVersion

XNB container format version. MonoGame's ContentManager accepts 4 or 5 and throws "Invalid XNB version" otherwise; mgcb writes 5.

public const byte FormatVersion = 5

Field Value

byte

Methods

PlatformIdentifierFor(PlatformTarget)

Returns the XNB platform identifier byte for target.

Derived from the target the consumer already picked — never asked for. The standing seamlessness directive forbids making a consumer opt in to get correct output, and measurement showed no opt-in is needed: MonoGame's ContentManager and FNA's both validate this byte only for membership in a whitelist, never against the platform actually running, so a correctly-derived byte always loads.

FNA's whitelist is the binding constraint and is smaller than MonoGame's: it has no 'V' (DesktopVK) and no 'G' (DirectX 12), which is why Fna maps to 'w' — the XNA Windows identifier, present in both lists.

public static char PlatformIdentifierFor(PlatformTarget target)

Parameters

target PlatformTarget

The platform backend the payload was compiled for.

Returns

char

Exceptions

ArgumentOutOfRangeException

target has no XNB platform identifier. Unreachable through the compiler: Metal is the only such target and the pipeline already rejects it with SD0200 long before any bytes exist to wrap.

Wrap(ReadOnlySpan<byte>, PlatformTarget)

Wraps effectPayload in an XNB container for target, deriving the platform identifier with PlatformIdentifierFor(PlatformTarget).

public static byte[] Wrap(ReadOnlySpan<byte> effectPayload, PlatformTarget target)

Parameters

effectPayload ReadOnlySpan<byte>

The compiled effect bytes — a .mgfx, .knifx, or FNA .fxb. Written verbatim; this writer never inspects or rewrites the payload.

target PlatformTarget

The platform backend the payload was compiled for.

Returns

byte[]

The complete .xnb file bytes.

Wrap(ReadOnlySpan<byte>, char)

Wraps effectPayload in an XNB container using an explicit platform identifier. Prefer the PlatformTarget overload; this one exists for the validation drivers, which must be able to produce a byte the derivation would not choose in order to prove the runtime's acceptance rules.

public static byte[] Wrap(ReadOnlySpan<byte> effectPayload, char platformIdentifier)

Parameters

effectPayload ReadOnlySpan<byte>

The compiled effect bytes, written verbatim.

platformIdentifier char

The XNB platform identifier character.

Returns

byte[]

The complete .xnb file bytes.