UTTORI ASM ยท IN DEVELOPMENT
Standalone asset conversion
Convert supplied PNG, WAVE, and data bytes to exact native outputs or explicit lossy BRR audio.
@uttori/asm-assets converts supplied bytes without an assembler, ROM, or filesystem. It works in Node and browser workers through the same synchronous registry API. The optional ./node entry point adds file reads and coordinated replacements.
import { AssetRegistry, convertAsset } from "@uttori/asm-assets";
import { pngImporter, withImageEncoders } from "@uttori/asm-assets/image";
import { snesNativeEncoders } from "@uttori/asm-assets/snes";
const registry = new AssetRegistry().registerImporter(pngImporter);
for (const encoder of withImageEncoders(snesNativeEncoders)) registry.registerEncoder(encoder);
const result = convertAsset(registry, {
source: { bytes: pngBytes, mediaType: "image/png" },
format: "snes.tile.4bpp",
options: { layout: { tileOrder: "row-major" } },
});
const tiles = result.outputs.tiles.bytes;
PNG conversion returns named tiles, palette, tilemap, and raw RGBA preview outputs. Indexed PNGs keep their palette and index identity; truecolor/grayscale inputs need an exact external palette or palette: "auto". Colors, alpha, dimensions, and layouts outside the selected native format are rejected. Native output reconstructs the imported pixel values and index information, not the original PNG container bytes.
Register waveImporter and withAudioEncoder from ./audio for mono PCM8/PCM16 WAVE-to-snes.brr. The result records sample rate, counts, loop and error measurements with lossy-audio fidelity, and includes decoded reviewWav bytes. It never promises PCM equality. Lossless byte transforms, including game compressors, must still decode to their exact input.
Indexed authoring helpers in ./image preserve palette index identity rather than matching colors.
extractIndexedRegion(), renderIndexedPlacements() and expandIndexedGrid() handle explicit
rectangles, flips and index mappings. rewriteIndexedPng() preserves palette slots and no-op bytes;
palette-only edits preserve compressed IDAT data. Imports reject animated/16-bit PNG and are
bounded to 16 MiB input, one megapixel, 5 MiB inflated scanlines and 16,384 chunks.
./aseprite, ./interchange, ./raster-interchange, ./indexed-ownership,
./animation-evidence and ./limits provide bounded saved-file presentation, native-owner
reconciliation and measured previews. Aseprite structure conversion uses asynchronous browser
compression streams. Saved Aseprite/PNG editing describes export,
review and application authority; presentation geometry and native animation timing remain read-only.
applyAssetFileChanges() from ./node validates exact before/after snapshots, stages replacements
and rolls back an ordinary publication failure without overwriting later edits. It is not crash-atomic
and does not allocate ROM space. Source-project hosts add journaled recovery and complete dependency
checks around saved asset application.
The package README lists limits, layouts, and standalone examples. See source inclusion and plugin registration.