Skip to content

Repository files navigation

@eriscorp/dalib-ts

TypeScript library for parsing and manipulating Dark Ages (DOOMVAS v1) game client files.

Translated from eriscorp/dalib, the original C# implementation, under the MIT license.


Installation

npm install @eriscorp/dalib-ts

Supported Formats

Format Class(es) Description
.dat DataArchive, DataArchiveEntry Game data archives
.map MapFile Map layout files
.meta MetaFile, MetaFileEntry Metadata files
.hpf HpfFile Tile graphics
.spf SpfFile, SpfFrame Sprite frames
.epf EpfFile, EpfFrame Entity / mob sprites
.mpf MpfFile, MpfFrame Map sprites
.efa EfaFile, EfaFrame Effect animations
.lft LftFile Bitmap fonts (the format the client actually renders text with)
.fnt / .hea FntFile, HeaFile Dormant fixed-cell fonts / light masks
sotp.dat SotpFile Static-tile collision & render flags
.tbl PaletteTable, ColorTable, TileAnimationTable, EffectTable Lookup tables
.control ControlFile, Control UI layout files

Usage

Reading a data archive (Node.js)

import { DataArchive } from '@eriscorp/dalib-ts';

const archive = DataArchive.fromFile('path/to/archive.dat');

// List all .spf entries
const sprites = archive.getEntriesByExtension('.spf');

// Get a specific entry's raw bytes
const entry = archive.get('sprite001.spf');
if (entry) {
  const buffer = archive.getEntryBuffer(entry);
}

Reading a data archive (browser)

import { DataArchive } from '@eriscorp/dalib-ts';

const response = await fetch('archive.dat');
const buffer = await response.arrayBuffer();
const archive = DataArchive.fromBuffer(buffer);

Parsing a sprite file

import { DataArchive, SpfFile, Palette } from '@eriscorp/dalib-ts';

const archive = DataArchive.fromFile('seo.dat');

const spfEntry = archive.get('sprite001.spf')!;
const palEntry = archive.get('sprite001.pal')!;

const spf = SpfFile.fromBuffer(archive.getEntryBuffer(spfEntry));
const palette = Palette.fromBuffer(archive.getEntryBuffer(palEntry));

Resolving the palette for a legacy entry

Legacy sprites do not carry their own colors. PaletteResolver applies the client's rules to find the correct palette for an entry:

import { DataArchive, PaletteResolver } from '@eriscorp/dalib-ts';

const archive = DataArchive.fromFile('legend.dat');
// The provider supplies sibling archives; return null when unavailable.
const resolver = new PaletteResolver('legend.dat', archive, name => null);

const resolved = resolver.resolve(archive.get('item001.epf')!, 0);
if (resolved) {
  // resolved.palette, resolved.paletteNumber, resolved.ruleId
  // resolved.luminanceBlended → render with straight (non-premultiplied) alpha
} else {
  // No rule matched, or data is missing — fall back to a manual picker.
}

Rendering to ImageData

import { renderSpfPalettized } from '@eriscorp/dalib-ts';

const frame = spf.frames[0];
const rgbaFrame = renderSpfPalettized(frame, palette);

// rgbaFrame.data is a Uint8ClampedArray — pass directly to ImageData
const imageData = new ImageData(rgbaFrame.data, rgbaFrame.width, rgbaFrame.height);
ctx.putImageData(imageData, 0, 0);

API Overview

Binary I/O

  • SpanReader — low-level binary reader (LE/BE integers, fixed-length ASCII, byte spans)
  • SpanWriter — low-level binary writer
  • compressHpf / decompressHpf — HPF tile compression

Cryptography

  • crc16(data) — CRC-16 checksum
  • crc32(data) — CRC-32 checksum

Utilities

  • decodeRgb555 / encodeRgb555 — RGB555 color codec
  • decodeRgb565 / encodeRgb565 — RGB565 color codec
  • quantizeFrames — palette quantization for image export
  • cropTransparentPixels — trim transparent borders from frames

Palette resolution

  • PaletteResolver — resolves the palette for entries of one open archive; returns ResolvedPalette (palette, paletteNumber, luminanceBlended, kind, ruleId) or null
  • matchPaletteRule(archiveName, entryName) — the pure rule-match stage, for tests and hosts that only need the ruleId
  • PaletteLookup.getResolvedPaletteForId(id, override?) — like getPaletteForId, and reports the real palette number plus the luminance-blending flag

Virtualized (lazy) Views

For large archives, avoid decoding everything upfront:

  • SpfView, EpfView, MpfView, EfaView, TilesetView

These decode individual frames on demand rather than parsing the entire file.


License

MIT

Releases

Packages

Contributors

Languages