npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tic80-image-tools

v0.0.1

Published

Export Tic-80 tiles and sprites to PNG images, and import image sheets back to cartridges.

Readme

Tic-80 Image Tools

Export and import Tic-80 tiles and sprites to/from PNG images.

👉 Read QUICKSTART.md for a 2-minute walkthrough

Features

  • Bidirectional - Export tiles and sprites to PNG and import them back
  • Multi-bank support - Handles all 8 TIC-80 memory banks automatically
  • Multi-palette - Exports all palettes per bank separately
  • Tile and sprite sheets - Separate full_tileset.png and full_spritesheet.png
  • Interactive CLI - Just run and follow prompts
  • Auto-detection - Finds .lua files in current directory
  • Color quantization - Automatically matches closest palette colors
  • Safe imports - Creates automatic backups before modifying cartridges
  • Bank targeting - Import to specific bank and palette
  • Standalone - No external tools needed
  • Fast - Converts tiles and sprites in milliseconds

Installation

Global (for any project)

npm install -g tic80-image-tools

Local (for a specific project)

npm install --save-dev tic80-image-tools

From GitHub

npm install --save-dev github:RafaelLVX/tic80-image-tools

Usage

Quick Start

Just run the CLI and follow the interactive prompts:

# If installed globally
tic80-img

# If installed locally in your project
npx tic80-img

Then:

  1. Choose operation: Export or Import
  2. For Export:
    • Choose your .lua cartridge (or enter a relative path like src/gamename.lua)
    • Choose format: Indexed PNG (only format that can be reintroduced to TIC-80)
    • Choose scale: 1x (only scale that can be reintroduced to TIC-80)
    • Done! PNGs appear in tileset_[cartridgename]/
  3. For Import:
    • Enter path to your edited sheet.png
    • Choose target cartridge to update
    • Confirm the operation (a backup is created automatically)
    • Done! Tiles are written back to the cartridge

Relative Paths

When the tool asks for a cartridge path, use relative paths from your current directory:

Example: If your project structure is:

my-game/
├── src/
│   ├── gamename.lua
│   ├── game2.lua
├── graphics/
└── tileset_tools/ (or just run from my-game/)

Run from my-game/ and enter: src/gamename.lua or src\gamename.lua

The tool resolves the path relative to where you run the command from, making it natural to integrate into your game development workflow.

Output

tileset_gamename/
├── palette.png          (color palette reference - 2×8 grid)
├── sheet.png            (all tiles combined)
├── tile_001.png
├── tile_016.png
├── tile_017.png
└── ... (tiles)

Example Workflows

Export Workflow

$ npx tic80-img

Then just follow the interactive prompts:

🎮 Tic-80 Image Tools

? What do you want to do? Export all tiles and sprites to PNG

? Enter path to .lua cartridge (relative to current directory): gamename.lua

📖 Parsing cartridge...
   Bank 0: 19 tiles, 8 sprites (2 palettes)

🎨 Converting tiles and sprites (indexed PNG)...
...................

📋 Creating tile sheet...
   ✓ tiles_sheet.png
📋 Creating sprite sheet...
   ✓ sprites_sheet.png
🎨 Creating palette reference...
   ✓ palette.png

✅ Export complete!
   Cartridge: gamename
   Output: D:\my-game\gamename_image_export/bank_0/palette_0/

Multi-bank cartridges automatically detect and extract all banks:

✅ Export complete!
   Cartridge: gamename
   Bank 0: 19 tiles, 8 sprites (2 palettes)
   Bank 1: 0 tiles, 0 sprites
   Bank 7: 5 tiles, 3 sprites (1 palette)
   Output: D:\my-game\gamename_image_export/

Import Workflow

After editing your tiles or sprites in an image editor:

🎮 Tic-80 Image Tools

? What do you want to do? Import tiles to cartridge

? Path to full tileset (PNG, max. 256 8x8-pixel tiles) gamename_image_export/bank_0/palette_0/full_tileset.png

? Enter cartridge path: gamename.lua

? Select target bank (0-7): 0

? Select target palette (0-1): 0

⚠️  Warning: This will overwrite tiles in Bank 0, Palette 0.
   A backup will be created automatically (.backup file).

? Proceed with import? Yes

📥 Importing tiles to cartridge...
   Source: full_tileset.png
   Target: gamename.lua (Bank 0, Palette 0)

🔍 Extracting tiles from sheet...
   Found 19 tiles

🔄 Converting to TIC-80 format and quantizing colors...

✅ Import complete!
   Imported: 19 tiles
   Updated: gamename.lua
   Backup: gamename.lua.backup

Key features of import:

  • Correct tile numbering: Follows TIC-80 grid layout (16 tiles per row) automatically
  • Automatic color quantization: Any colors in your edited PNG are matched to the closest colors in the cartridge's palette (though using exact palette colors are recommended)
  • Safe operation: Always creates a .backup file before modifying the cartridge
  • Flexible input: Works with sheets at any scale (1x, 2x, 4x, 8x) - automatically downsampled to 8×8 tiles (though 1x is recommended)

Tile Grid Layout

TIC-80 organizes tiles in a 16×16 grid (0-255). When you import a sheet, tiles are positioned based on their location:

Standard 16-wide sheet (full width):

Row 0: tiles 0-15
Row 1: tiles 16-31
Row 2: tiles 32-47
...

Sheet requirements:

  • Width: Must be exactly 128px, 256px, 512px, or 1024px (16 tiles wide at 1x, 2x, 4x, or 8x scale)
  • Height: Can be any multiple of 8px, up to 16 rows (fewer than 16 rows is fine if you don't need all 256 tiles)
  • Scaling: The tool samples the center pixel of each scaled tile to convert back to 8×8

Example: A 256×128 PNG (16-wide at 2x scale, 8 rows) imports tiles 0-127.

The tool automatically calculates tile IDs based on position:

tileId = (row * 16) + col

Important: The tool assumes your sheet starts at tile 0. If you need a different starting tile, extract your cartridge with the export function first, and it will match the original layout automatically.

Color Quantization

When importing tiles back to the cartridge, the tool automatically matches each pixel color to the closest color in the cartridge's 16-color palette.

Algorithm: Euclidean distance in RGB color space

distance = sqrt((R1-R2)² + (G1-G2)² + (B1-B2)²)

How it works:

  1. Read each pixel from your edited sheet.png
  2. Calculate color distance to all 16 palette colors
  3. Select the palette color with minimum distance
  4. Use that palette index (0-15) in the tile data

Best practices:

  • Use the palette.png reference to see exact cartridge colors.
  • You CAN edit at larger scales (2x, 4x) if you find it easier to draw, but the tool will automatically downsample the full set 1x when importing.
  • Colors slightly off-palette will snap to nearest match.

Format Options

Indexed PNG (Default)

  • Color palette: Exact 16-color palette from cartridge embedded in PNG (8-bit) (theoretically the only format that can be safely reintroduced to cartridge, though the tool will attempt to match colors to existing palettes).
  • Important: Image editors will typically convert indexed PNG to RGB for editing, discarding palette information. Be careful when adding new colors to try match existing color palettes as best you can.

RGB PNG

  • Color palette: Full RGB color space (not indexed, reducing TIC-80 compatibility).
  • Use case: Viewing, sharing, or external use.

Output Location

By default, the tileset folder is created next to your cartridge:

gamename_image_export/
├── bank_0/
│   ├── palette_0/ (tiles, sprites, palette.png)
│   └── palette_1/ (if available)
├── bank_1/
│   └── palette_0/
...
└── bank_7/
    └── palette_0/

What It Does

Cartridge Parsing

  • Extracts the <PALETTE> section (16 RGB colors)
  • Extracts the <TILES> sections (8×8 pixel tiles, or up-scaled on demand)
  • Extracts the <SPRITES> sections (8×8 pixel sprites, or up-scaled on demand)

Image Generation

  • Converts color indices to RGB values
  • Renders pixel data to PNG format
  • Upscales for better visibility or shareability (optional)
  • Creates combined full tileset and spritesheet
  • Exports image with palette color reference

Requirements

  • Node.js 14.0.0 or higher
  • npm or yarn

Limitations

This tool currently only supports a limited set of TIC-80 cartridges:

  • Lua files (gamename.lua)
  • Saved from PRO version of TIC-80
  • 4 bits per pixel

The tool might work to an extent with non-Lua cartridges depending on how they're structured, but this was never tested. It will not work on .tic files at all.

The tool was never tested with 2 or 1 bit per pixel, and it's not expected to work in those cases.

How It Works

Tic-80 stores tiles as hex-encoded data:

  • Each tile = 64 hex characters
  • Each character = one pixel (0-15 = color index)
  • Palette maps color indices to RGB values

Example:

-- <PALETTE>
-- 000:1a1c2c5d275db13e53...  (16 colors, 6 hex chars each)
-- </PALETTE>

-- <TILES>
-- 020:ccccccccffffffffffffffffffffffffffffffffffffffffffffffffffffffff
--     ↑ tile 20: 'c' = color 12, 'f' = color 15
-- </TILES>

The tool:

  1. Parses hex strings to color indices
  2. Looks up each color in the palette
  3. Renders to PNG with proper RGB values

Troubleshooting

"No palette found"

  • Make sure you're using a valid Tic-80 .lua cartridge file

"No TILES section"

  • Your cartridge has an empty tileset

"File not found"

  • Check the path and make sure the file exists

License

MIT - Use freely in your projects.

Related

Future Roadmap (?)

  • [ ] Palette editing
  • [ ] Support for 2/1 bits per pixel
  • [ ] Support for other programming languages (non-Lua)
  • [ ] Map export/import

Support

For issues or questions:

  • Check the Tic-80 documentation
  • Review example cartridges
  • File an issue on GitHub