Metadata-Version: 2.4
Name: tile2sam
Version: 1.3.0
Summary: Convert SAM Coupé graphics to Z80 code or data
Project-URL: Homepage, https://github.com/simonowen/tile2sam
Author-email: Simon Owen <simon@simonowen.com>
License-Expression: MIT
License-File: LICENSE.md
Keywords: coupe,graphics,sam,tile
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Multimedia :: Graphics :: Graphics Conversion
Classifier: Topic :: Software Development :: Code Generators
Classifier: Topic :: Utilities
Requires-Python: >=3.10
Requires-Dist: pillow>=8.0.0
Description-Content-Type: text/markdown

# tile2sam

A Python script to convert SAM Coupé graphics images to Z80 code or data.

Generated code is sprite-specific and highly optimised. Or provide your own
drawing routines for the extracted graphics data.

## Installation

Installing the tool doesn't require the source code or even Python, just uv.

Install [uv](https://docs.astral.sh/uv/#installation) if not already installed.
Windows users can do that using:

```shell
winget install --id=astral-sh.uv -e
```

Then install the `tile2sam` command using:

```shell
uv tool install tile2sam
```

## Command-line Options

```text
usage: tile2sam [-h] [-m MODE] [-c CLUT] [-o OUTPUT] [-a] [-p] [-i] [-b BKGCOL] [-t TILES] [-z CODE] [-n NAMES] [-0]
                [-v] [--version] [--crop CROP] [--scale SCALE] [--shift SHIFT] [--share] [--timings]
                image [tilesize]

Convert SAM Coupé graphics images to Z80 code or data.

positional arguments:
  image
  tilesize              tile size (WxH or W) (default: None)

options:
  -h, --help            show this help message and exit
  -m MODE, --mode MODE  output data screen mode (1-4) (default: 4)
  -c CLUT, --clut CLUT  custom colour file or list (default: None)
  -o OUTPUT, --output OUTPUT
                        custom output filename (default: None)
  -a, --append          append to existing output file (default: False)
  -p, --pal             write clut to .pal file (default: False)
  -i, --index           write offsets index to .idx (default: False)
  -b BKGCOL, --bkgcol BKGCOL
                        background colour (0-127) (default: None)
  -t TILES, --tiles TILES
                        tile count or list of ranges (N-M) (default: None)
  -z CODE, --code CODE  Z80 routines to generate (default: None)
  -n NAMES, --names NAMES
                        Names for sprite labels (default: None)
  -0, --low             screen at 0 instead of 0x8000 (default: False)
  -v, --verbose         verbose mode (default: False)
  --version             show program's version number and exit
  --crop CROP           crop region (WxH or WxH+X+Y) (default: None)
  --scale SCALE         scale region (S or HxV) (default: None)
  --shift SHIFT         pixels to shift right (default: None)
  --share               share even/odd save/restore code (default: False)
  --timings             show nominal code timings (default: False)
```

The `-q, --quiet` option in earlier versions is now the default behaviour. Use
the new `-v, --verbose` options to display conversion details.

## Required Arguments

> image

An image file containing the graphics data. Most image file formats are
[supported](https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html),
but it's recommended you use an efficient lossless format such as
[PNG](https://en.wikipedia.org/wiki/Portable_Network_Graphics).

Image colours are mapped to the nearest SAM palette colour, without any
dithering. Images with too many source colours may be rejected. Typically you'll
want to author graphics directly using the original SAM palette colours:

![SAM palette](https://raw.githubusercontent.com/simonowen/tile2sam/refs/heads/main/sampalette.png)

Tiles are extracted starting from the top-left of the image. Use the `--crop`
and `--scale` options to limit the area of interest. Use `--tiles` to select the
tiles of interest, and the order they're extracted. The extracted graphics may
also be pre-shifted using `--shift`.

> tilesize

Specifies the dimensions of the tiles to extract, in pixels. If a single value
`N` is given it's treated as having a size of `NxN`. If both dimensions are
specified they should be in the format `WxH`.

If the tile width does not result in an exact number of output bytes, the right
edge is padded with background pixels. To be aligned to byte boundaries, mode 4
tile width should be a multiple of 2, mode 3 a multiple of 4, and modes 1 and 2
a multiple of 8.

## Optional Arguments

> `-z, --code CODE`

Specifies a comma-separated list of Z80 routines to generate for each sprite,
instead of binary graphics data. The available routines are:

- `masked` - draw to display with partial byte masking [label: masked_*name*]
- `unmasked` - draw to display *without* masking partial bytes [label: unmasked_*name*]
- `save` - save display area affected by drawn sprite [label: save_*name*]
- `restore` - restore previously saved area [label: restore_*name*]
- `copy` - remove drawn sprite by copying from alternate screen [label: copy_*name*]
- `clear` - clear display area affected by drawn sprite [label: clear_*name*]
- `rect` - clear routine for rectangle covering the sprite area [label: clear_rect_*WB*x*H*]

### Notes

- Specifying `save` or `restore` generates both routines.
- A save_*name*_size symbol is defined to hold the save buffer size in bytes.
- 'copy' expects a screen source in the opposite 32K from the drawn display.
- `rect` generates a label name using the width (in bytes) and height of the
  sprite. To avoid duplicate labels and code this should generally be given as
  the only routine, once per sprite size.
- See my [blog article](https://simonowen.com/blog/2020/05/04/tile2sam-code/)
  for more details on code generation.

> `--names NAMES`

Specifies a comma-separated list of names to use for sprite code labels. Missing
names are assigned `spriteN`, where `N` is the zero-based index of the sprite in
the image file.

> `--low`

Convert coordinates to display addresses in low memory (based at address 0). The
default generates addresses in high memory (based at address 0x8000).

> `-m MODE, --mode MODE`

Selects the SAM screen mode (1 to 4) used for both output data format and colour
selection. Modes 1 and 2 are produce the same 1-bit format, with only 2 colours.
Mode 3 is a 2-bit mode with 4 colours. Mode 4 is a 4-bit mode with 16 colours.

The default screen mode is 4.

> `-c CLUT, --clut CLUT`

Specifies either a comma-separated list of colours, or the name of a `.pal` file
containing the palette. Each colour should be in the range 0-127.

A complete palette is not required, but those specified will be assigned to the
first CLUT slots. Any additional colours required by the image will be
automatically assigned to later positions. The final CLUT size must be within
the limit for the screen mode (sixteen colours for mode 4, four colours for mode
3, and two colours for modes 1 and 2).

If no CLUT is provided and the image colours are a subset of the BASIC mode 4
colours, they will be used instead. Otherwise a CLUT will be generated from the
colours in the source image.

> `-o OUTPUT, --output OUTPUT`

Specify a custom output file, which defaults to a `.bin` extension for data
output and `.asm` for code output. The same basename is also used for `.pal` and
`.idx` files if they are enabled.

The default behaviour uses the basename of the input image, so `image.png` will
generate `image.dat`.

With code generation, using an output file of `-` will write the code to stdout.

> `-p, --pal`

Write the corresponding palette to a `.pal` file, which is a binary file
containing 1 byte per colour. The palette file may then be used as an input file
using the `--clut` option, or imported into source code using using `MDAT`.

The default behaviour displays the list of colours to the console but does not
save it to a file.

> `-i, --index`

Generate an index of data offsets to each output tile. Each entry is a 16-bit
value in little-endian format. While the entries are simple multiples of the
tile data size, multiple index files from different invocations may be combined
to give a more useful look-up table.

The default behaviour is not to output an index.

> `-b, --bkgcol`

Specifies a SAM palette colour to treat as the background of the source image.
The background colour is treated as transparent, and is not added to the CLUT
colours. All other colours are treated as opaque foreground colours.

If no background colour is specified but the source image contains a palette
with alpha transparecy, any colours with zero alpha are treated as background.
Otherwise palette colour 0 (black) is treated as transparent.

> `-t TILES, --tiles TILES`

Selects the tiles to extract from the image. If a single value is given it's
treated as a count of tiles to extract from the top-left of the image. You may
also specify a comma-separated list of tile numbers, which can include ranges of
tiles in an A-B (inclusive) notation. If the range start is greater than the end
that portion is extracted in reverse order.

The default behaviour is to extract as many complete tiles from the image as
possible.

> `-a, --append`

Append to any existing output file, rather than creating a new file.

> `-v, --verbose`

Show details about processing, which are hidden by default. Error messages are
always shown.

> `--crop CROP`

Crop the input image so tiles are only extracted from a specific portion of it.
The crop region can be just a size in WxH format, or a size and a top-left
coordinate in WxH+X+Y format. Cropping is performed before any scaling (see
below).

The default behaviour is not to crop the input image.

> `--scale SCALE`

Scale the input image before extraction, which is useful for pixel-doubled and
mode 3 content. Scaling uses a nearest neighbour pixel matching, and is
performed after any cropping (see above).

The default behaviour is not to scale the input image.

> `--shift SHIFT`

Specifies the number of pixels to shift each tile to the right in the output
data. This will add padding to the left of the data, and may also result in
additional alignment padding to the right. All padding uses CLUT entry zero,
which will usually be black.

This option can be used to create pre-shifted versions of graphics for optimised
drawing routines. The default behaviour is not to shift content.

Using `--shift 0` with code generation will suppress the code for odd x
positions. The default behaviour generates code for both even and odd positions.

> `--share`

Used by code generation, causing the code generated by save/restore to cover
both even and odd shift positions. This reduces the amount of code generated
with only a small increase in execution time.

Note: If your sprite use a full even width the shifted odd position will spill
into a new display byte. Restoring a drawn sprite at the extreme right edge of
the display may overflow into the next screen row, or a byte beyond the end of
the display file. Use with care!

> `--timings`

Shows the nominal code timings in t-states for each type of code generation
routine, to help compare different methods.

## Examples

Extract all 16x16 tiles from `sprites.png`, write the graphics data to
`sprites.bin` and palette to `sprites.pal`:

```shell
tile2sam --pal sprites.png 16x16
```

Extract the first 100 6x6 tiles from `tiles.png`, using the colours from
`sprites.pal`:

```shell
tile2sam --clut sprites.pal --tiles 100 tiles.png 6x6
```

Extract a non-contiguous selection of 6x6 tiles from `tiles.png`:

```shell
tile2sam --tiles 10-19,99-90,42 tiles.png 6
```

Extract a 6x8 1-bit font from `font.png`, write the data to `font.bin`:

```shell
tile2sam --mode 2 font.png 6x8
```

Extract a 6x8 1-bit font from `font.png`, shifting the data 2 positions to
right-align it, then write to `font_centre.bin`:

```shell
tile2sam --mode 2 --shift 2 -o font_centre.bin font.png 6x8
```

Extract all 12x12 sprites from `sprites.png`, fixing only the first 4 CLUT
colours so the rest are automatically assigned:

```shell
tile2sam --clut 0,127,25,126 sprites.png 12
```

Extract a mode 4 screen from a 576x480 SimCoupe screenshot to `mode4.bin` and
`mode4.pal`:

```shell
tile2sam --crop 512x384+32+48 --scale 0.5 --pal mode4.png 256x192
```

Extract a mode 3 screen from a 576x480 SimCoupe screenshot to `mode3.bin` and
`mode3.pal`:

```shell
tile2sam --crop 512x384+32+48 --scale 1.0x0.5 --mode 3 --pal mode3.png 512x192
```

Extract a mode 2 screen from a 576x480 SimCoupe screenshot to `mode2.bin`:

```shell
tile2sam --crop 512x384+32+48 --scale 0.5x0.5 --mode 2 mode2.png 256x192
```

Generate code to draw masked 11x11 sprites from a mode 4 image:

```shell
tile2sam --code masked,save --names cherry,strawb,orange --pal sprites.png 11x11
```

Generate and append code to draw unmasked 11x11 tiles from a mode 4 image:

```shell
tile2sam -a --code unmasked,clear --names cherry,strawb,orange --pal sprites.png 11
```

Generate code to draw a masked 11x11 sprite only at even x positions:

```shell
tile2sam --code masked,save --names ghost --shift 0 --pal ghost.png 11x11
```

Generate code to draw a masked 11x11 sprite, restoring from clean screen copy:

```shell
tile2sam --code masked,copy --names ghost --pal ghost.png 11x11
```

Full example programs are available from the tile2sam [GitHub
repository](https://github.com/simonowen/tile2sam), under the demos directory.

## License

This project is licensed under the MIT License - see the
[LICENSE.md](LICENSE.md) file for details

## Author

Simon Owen  
[https://simonowen.com](https://simonowen.com)
