@eriscorp/dalib-ts
v3.1.1
Published
JavaScript/TypeScript library for parsing and manipulating Dark Ages (DOOMVAS v1) game client files
Maintainers
Readme
@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-tsSupported 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 writercompressHpf/decompressHpf— HPF tile compression
Cryptography
crc16(data)— CRC-16 checksumcrc32(data)— CRC-32 checksum
Utilities
decodeRgb555/encodeRgb555— RGB555 color codecdecodeRgb565/encodeRgb565— RGB565 color codecquantizeFrames— palette quantization for image exportcropTransparentPixels— trim transparent borders from frames
Palette resolution
PaletteResolver— resolves the palette for entries of one open archive; returnsResolvedPalette(palette,paletteNumber,luminanceBlended,kind,ruleId) ornullmatchPaletteRule(archiveName, entryName)— the pure rule-match stage, for tests and hosts that only need theruleIdPaletteLookup.getResolvedPaletteForId(id, override?)— likegetPaletteForId, 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.
