Documentation
¶
Overview ¶
Package tsf implements reading, writing, compiling and decompiling of Total Annihilation: Kingdoms truecolor animation files.
TA: Kingdoms stores animations in two related forms:
TAF: a compiled binary container. It reuses the Total Annihilation GAF layout (version 0x00010100, an entry-pointer table, per-frame info records and a frame list) but stores 16-bit truecolor pixels instead of 8-bit palette indices. Each frame carries a pixel-format flag selecting ARGB4444 or ARGB1555.
TSF: the human-readable text form of the same data. It is a brace delimited, INI-like document describing an animation as a tree of frames and layers, where each layer references an external image file. The game's GUI loader consumes TSF directly for menu backgrounds.
This package can parse and re-emit both forms byte-for-byte, decompile a binary TAF into a TSF document plus extracted layer images, and compile a TSF document plus its images back into a binary TAF.
Index ¶
- Constants
- func Decompile(t *TAF, baseName string) (*Document, []ImageFile, error)
- func PixelsFromNRGBA(img *image.NRGBA, format PixelFormat) ([]byte, error)
- type Assignment
- type DirResolver
- type Document
- type Frame
- type ImageFile
- type ImageResolver
- type LintDiagnostic
- type LintLevel
- type MemoryResolver
- type Node
- type PixelFormat
- type Section
- type TAF
- func Compile(doc *Document, res ImageResolver) (*TAF, error)
- func FromGIF(g *gif.GIF, format PixelFormat, name string) (*TAF, error)
- func FromSheet(img image.Image, frameW, frameH, count int, format PixelFormat, name string, ...) (*TAF, error)
- func ParseTAF(data []byte) (*TAF, error)
- func ReadTAF(r io.Reader) (*TAF, error)
- func (t *TAF) Bytes() ([]byte, error)
- func (t *TAF) CanvasBounds() (image.Rectangle, error)
- func (t *TAF) FrameImage(i int) (*image.NRGBA, error)
- func (t *TAF) Lint() []LintDiagnostic
- func (t *TAF) RenderSheet(cols int, bg color.Color) (*image.NRGBA, error)
- func (t *TAF) ToAPNG(w io.Writer) error
- func (t *TAF) ToGIF() (*gif.GIF, error)
Constants ¶
const Version uint32 = 0x00010100
Version is the format version stored in every TA: Kingdoms TAF header. It is identical to the Total Annihilation GAF version.
Variables ¶
This section is empty.
Functions ¶
func Decompile ¶
Decompile converts a binary TAF into an equivalent TSF document plus one PNG per frame. The document records every detail needed to recompile the exact original bytes: per-frame pixel format, placement, duration and the preserved frame flag. Compiling the returned document with an ImageResolver backed by the returned images reproduces the original TAF byte-for-byte.
baseName is used to derive image filenames (baseName_<frame>.png). When empty, the TAF's sequence name is used, falling back to "frame".
func PixelsFromNRGBA ¶
func PixelsFromNRGBA(img *image.NRGBA, format PixelFormat) ([]byte, error)
PixelsFromNRGBA encodes a non-premultiplied RGBA image into packed 16-bit pixels in the requested format. It is the exact inverse of ToNRGBA for any image that ToNRGBA produced.
Types ¶
type Assignment ¶
Assignment is a "Key = Value;" statement.
type DirResolver ¶
type DirResolver string
DirResolver resolves filenames against a directory on disk. Lookups are case-insensitive to match the game's tolerant filename handling.
type Document ¶
type Document struct {
// Leading holds verbatim lines that appear before the first section
// (typically a comment and a blank line).
Leading []string
// Sections holds the top-level sections in order.
Sections []*Section
// Trailing holds verbatim lines that appear after the last section.
Trailing []string
// LineEnding is the terminator used between lines ("\r\n" or "\n").
LineEnding string
}
Document is a parsed TSF text file: an optional block of leading trivia (comments and blank lines), one or more top-level sections, and any trailing trivia. Re-serializing a parsed Document reproduces the original bytes.
type Frame ¶
type Frame struct {
Width uint16
Height uint16
OriginX int16
OriginY int16
Format PixelFormat
Duration uint32 // playback duration in game ticks (1/30th second)
// Pixels holds Width*Height little-endian 16-bit values in the frame's
// PixelFormat.
Pixels []byte
// contains filtered or unexported fields
}
Frame is a single animation frame: a rectangle of 16-bit truecolor pixels plus placement and timing metadata.
type ImageFile ¶
ImageFile is a layer image produced when decompiling a TAF. Name is the filename referenced from the TSF document; Data is the encoded PNG.
type ImageResolver ¶
ImageResolver loads a layer image referenced by a TSF Filename and returns it as a non-premultiplied RGBA image.
type LintDiagnostic ¶
LintDiagnostic is a single finding from Lint or LintDocument. Frame is the zero-based frame index, or -1 for a file-level finding.
func LintDocument ¶
func LintDocument(doc *Document) []LintDiagnostic
LintDocument checks that a TSF document matches the animation shape the compiler expects: one animation section, each frame holding exactly one layer with a Filename. It does not load the referenced images.
type MemoryResolver ¶
MemoryResolver resolves filenames against an in-memory map of PNG bytes.
func NewMemoryResolver ¶
func NewMemoryResolver(files []ImageFile) MemoryResolver
NewMemoryResolver builds a MemoryResolver from decompiled image files.
type Node ¶
type Node interface {
// contains filtered or unexported methods
}
Node is one element of a section body: either an *Assignment or a *Section.
type PixelFormat ¶
type PixelFormat uint8
PixelFormat selects the 16-bit encoding used for a frame's pixels.
const ( // FormatARGB4444 packs each pixel as 4 bits of alpha, red, green and blue. FormatARGB4444 PixelFormat = 4 // FormatARGB1555 packs each pixel as 1 bit of alpha and 5 bits each of // red, green and blue. FormatARGB1555 PixelFormat = 5 )
func ParsePixelFormat ¶
func ParsePixelFormat(s string) (PixelFormat, error)
ParsePixelFormat maps a case-insensitive format name ("ARGB4444"/"4444" or "ARGB1555"/"1555") to its PixelFormat. It is the public entry point used by import tooling.
func (PixelFormat) BytesPerPixel ¶
func (p PixelFormat) BytesPerPixel() int
BytesPerPixel is always 2 for the truecolor TAF formats.
func (PixelFormat) String ¶
func (p PixelFormat) String() string
String returns a stable textual name for the pixel format, used in TSF documents.
type Section ¶
Section is a named brace-delimited block. Its body is an ordered list of assignments and nested sections.
func (*Section) Get ¶
Get returns the value of the first assignment with the given key and whether it was found. Section nodes are ignored.
func (*Section) Subsections ¶
Subsections returns the nested sections of s in order.
type TAF ¶
type TAF struct {
// Name is the sequence name as stored in the 32-byte name field.
Name string
// Frames holds the animation frames in playback order.
Frames []*Frame
// contains filtered or unexported fields
}
TAF is a parsed TA: Kingdoms animation file. Every retail TAF contains a single animation sequence, which this type models directly.
func Compile ¶
func Compile(doc *Document, res ImageResolver) (*TAF, error)
Compile builds a binary TAF from a TSF document, loading each layer image through res. The document's first section is treated as the animation.
The per-frame pixel format is taken from a "Format" assignment in the frame section (defaulting to ARGB4444), the duration from "Delay", and the placement from the layer's "AnchorX"/"AnchorY". A "Flags" assignment, when present, restores the preserved frame-info byte so a decompiled animation can be recompiled byte-for-byte.
func FromGIF ¶
FromGIF builds a TAF from a decoded animated GIF. Every GIF frame is flattened against the running canvas (honouring background/none disposal) so each TAF frame is a full-size truecolor image in the requested format. GIF delays (1/100s) are converted back to TA: Kingdoms ticks.
func FromSheet ¶
func FromSheet(img image.Image, frameW, frameH, count int, format PixelFormat, name string, duration uint32) (*TAF, error)
FromSheet slices a sprite-sheet image into frames of frameW×frameH, walking left-to-right then top-to-bottom. When count is zero every full cell is taken; otherwise the first count cells are used. Each frame is given the same duration (in ticks).
func ParseTAF ¶
ParseTAF parses a TAF file from a byte slice. The format is pointer-based, so the whole file must be available.
func (*TAF) Bytes ¶
Bytes serializes the TAF back into its binary form. For any TAF produced by ParseTAF the result is byte-identical to the original file.
func (*TAF) CanvasBounds ¶
CanvasBounds returns the bounding box that contains every frame once each is positioned by its origin. The rectangle is expressed in origin space, so its Min may be negative; its width and height give the canvas size an animation renders into.
func (*TAF) FrameImage ¶
FrameImage decodes frame i to a non-premultiplied RGBA image at its own dimensions (origin ignored).
func (*TAF) Lint ¶
func (t *TAF) Lint() []LintDiagnostic
Lint inspects a parsed TAF for structural problems and curiosities. An empty result means the animation is clean and will serialize byte-cleanly.
func (*TAF) RenderSheet ¶
RenderSheet lays every frame out in a grid sprite sheet with cols columns. Each cell is sized to the largest frame; smaller frames are anchored top-left. When bg is nil the sheet background stays transparent.
func (*TAF) ToAPNG ¶
ToAPNG renders the animation to an animated PNG, preserving the full RGBA channels (including partial alpha). A single-frame animation is written as a plain PNG.