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. Identical to mgcb's field for field; the one value that deliberately differs is the reader name (see EffectReaderTypeName):

'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: the XNA 4.0 name, which is what XNA itself wrote and what KNI's own content pipeline (CompiledEffectWriter) still writes.

This is the only reader name measured to load on every consumer runtime (Phase 64, 2026-09-09: MonoGame 3.8.1.263 / 3.8.2.1105 / 3.8.5, KNI 4.2.9001 / 4.3.9001, FNA 26.06 — each a real ContentManager.Load<Effect> rendering pixel-identical to that runtime's reference). It is the intersection of three resolvers that all strip the version but do not agree on anything else:

  • MonoGame (ContentTypeReaderManager.PrepareType) strips the version only when the name contains PublicKeyToken, then replaces , Microsoft.Xna.Framework.Graphics with its own assembly name.
  • FNA matches one compiled regex requiring the full , <assembly>, Version=…, Culture=…, PublicKeyToken=… triple with the assembly being one of Microsoft.Xna.Framework[.Graphics|.Video] or MonoGame.Framework; a bare …, MonoGame.Framework does not match.
  • KNI (ContentTypeReaderManager.ResolveReaderType) maps , Microsoft.Xna.Framework.Graphics to Xna.Framework.Graphics first. The mgcb-shaped name (…, MonoGame.Framework, Version=3.8.4.1, …) takes a later branch that appends KNI's assembly name to the stripped string and calls Type.GetType on a two-assembly name, which throws FileLoadException: The given assembly name was invalid. on KNI ≤ 4.2.9001 (4.3.9001 catches it). Stock mgcb's own .xnb fails on KNI 4.2 for exactly this reason, so "emit what mgcb emits" — Phase 60's first choice — was wrong for KNI.

The version and token values are inert on every runtime; the shape is what is load-bearing. One string everywhere: deriving a per-runtime manifest would make a consumer opt in to get correct output, which the seamlessness directive forbids.

public const string EffectReaderTypeName = "Microsoft.Xna.Framework.Content.EffectReader, Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553"

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.