/texconv

A texture creation tool for the SEGA Dreamcast.

Primary LanguageC++

texconv is a utility for creating textures for the SEGA Dreamcast hardware.

Requires Qt 5.2 or newer.

Supports all image formats supported by Qt. 
At the time I'm writing this, these formats are supported:

Format	Description								Qt's support
BMP		Windows Bitmap							Read/write
GIF		Graphic Interchange Format (optional)	Read
JPG		Joint Photographic Experts Group		Read/write
JPEG	Joint Photographic Experts Group		Read/write
PNG		Portable Network Graphics				Read/write
PBM		Portable Bitmap							Read
PGM		Portable Graymap						Read
PPM		Portable Pixmap							Read/write
XBM		X11 Bitmap								Read/write
XPM		X11 Pixmap								Read/write



USAGE
=====

texconv --in <filename> --out <filename> --format <pixelformat> [flags...]



EXAMPLES
========

texconv --in img.jpg --out a.tex --format RGB565
	Creates an RGB565 texture called 'a.tex' using 'img.jpg' as input.

texconv --in img.jpg --out a.tex --format PAL8BPP
	Creates an 8-bit paletted texture called 'a.tex' using 'img.jpg' as input.
	A palette file 'a.tex.pal' will also be created.

texconv --in img.jpg --out a.tex --format YUV422 --compress --mipmap
	Creates a compressed, mipmapped YUV texture 'a.tex' using 'img.jpg' as
	input.

texconv --in img1.jpg --in img2.png --format RGB565 --mipmap
	Also assuming "img1.jpg" is 64x64 and 'img2.png' is 16x16, creates a
	mipmapped RGB565 texture with mipmap levels like this:
		64x64 - 'img1.jpg'
		32x32 - 'img1.jpg' (downscaled)
		16x16 - 'img2.png'
		  8x8 - 'img2.png' (downscaled)
		  4x4 - 'img2.png' (downscaled)
		  2x2 - 'img2.png' (downscaled)
		  1x1 - 'img2.png' (downscaled)

texconv --in img.jpg --out a.tex --format PAL4BPP --compress 
		--preview preview.png --vqcodeusage usage.png
	Creates a compressed 4-bit paletted texture 'a.tex' using 'img.jpg' as
	input. A palette file 'a.tex.pal' will also be created. A preview file
	'preview.png' showing what the texture looks is generated as well as
	an image 'usage.png' that visualizes codebook usage for 'a.tex'.


GENERAL INFO
============

These are all limitations set by the hardware.

*	Input image dimensions must be one of the following: 8, 16, 32, 64, 128, 
	256, 512 or 1024. There are two exceptions to this rule, see the -mipmap
	and -stride flags for more info.

*	Mipmapped textures must be square.

*	Strided textures can't be compressed, twiddled or mipmapped.

*	Bumpmaps and paletted textures can't be strided.


PIXEL FORMATS
=============

RGB565 
	16-bit RGB texture without alpha.

ARGB1555 
	16-bit texture with 1-bit alpha. Each texel is either fully opaque or fully
	transparent.

ARGB4444
	16-bit texture with full alpha.

YUV422
	16-bit texture without alpha. The YUV color space takes human perception 
	into account, and thus offers higher percieved quality than the RGB color 
	space.

BUMPMAP
	16-bit normal map. Each texel consist of a pair of 8-bit values (S and R)
	which represent a normal in spherical coordinates.
	S = polar angle. 0-255 maps to 0-89 degrees.
	R = azimuthal angle. 0-255 maps to 0-359 degrees.

PAL4BPP
	4BPP paletted texture. The palette can contain a maximum of 16 colors.
	If the input images contain more colors than the palette can hold, 
	the color count will be automatically reduced by the converter.
	An additional palette file <outfile>.pal will be written for this format.

PAL8BPP
	8BPP paletted texture. The palette can contain a maximum of 256 colors.
	If the input images contain more colors than the palette can hold, 
	the color count will be automatically reduced by the converter.
	An additional palette file <outfile>.pal will be written for this format.



PROGRAM FLAGS
=============

-i <filename> or -in <filename>
	One or more images to use as input. Specify one image for non-mipmapped 
	textures and one or more images for	mipmapped textures.

-o <filename> or -out <filename>
	Output file.

-f <format> or -format <format>
	One of the aforementioned pixel formats.

-m or -mipmap
	Generate/allow mipmaps. If this flag is specified, you can supply 
	additional images down to a 1x1 size with the '-in' flag to be used for the
	different mipmap levels. Keep in mind though that at least one image must
	be 8x8 or larger. Any missing mipmap levels will be generated by 
	downscaling the	next size up.

-c or -compress
	Output a compressed texture. Compressed textures are 1/8th the size of 
	their uncompressed counterparts, plus a 2kB codebook overhead per texture.

-s or -stride
	Output a strided texture. Strided textures allow for the width of the 
	texture to be any multiple of 32 from 32 to 992. See the topic on strided 
	textures for more info.

-p <filename> or -preview <filename>
	Generate a preview image showing what the texture looks like. 

-v or -verbose
	Extra printouts. The converter will only print warnings and errors unless
	this flags is set.

-n or -nearest
	Use nearest-neighbor filtering when generating missing mipmap levels. This
	is the default filter for paletted, mipmapped textures to avoid introducing
	additional colors to the palette.

-b or -bilinear
	Use bilinear filtering when generating missing mipmap levels. This is the
	default filter for all 16-bit textures, for higher quality mipmaps.

-vqcodeusage <filename>
	Outputs an image that visualizes compression code usage. Will only do 
	something for compressed textures.



TEXTURE FILE FORMAT
===================

Each texture starts with a 16-byte header:

typedef struct {
	char	id[4];	// 'DTEX'
	short	width;
	short	height;
	int		type;
	int		size;
} header_t;

It is then followed by 'size' bytes of texture data which can be uploaded 
directly to VRAM. The size will always be a multiple of 32 bytes to allow
for DMA transfers.

'type' contains the various flags and the pixel format packed together:
bits 0-4 : Stride setting.
	The width of stride textures is NOT stored in 'width'. To get the actual
	width, multiply the stride setting by 32. The next power of two size up
	from the stride width will be stored in 'width'.
bit 25 : Stride flag
	0 = Non-strided
	1 = Strided
bit 26 : Untwiddled flag
	0 = Twiddled
	1 = Untwiddled
bits 27-29 : Pixel format
	0 = ARGB1555
	1 = RGB565
	2 = ARGB4444
	3 = YUV422
	4 = BUMPMAP
	5 = PAL4BPP
	6 = PAL8BPP
bit 30 : Compressed flag
	0 = Uncompressed
	1 = Compressed
bit 31 : Mipmapped flag
	0 = No mipmaps
	1 = Mipmapped



PALETTE FILE FORMAT
===================

Each palette starts with an 8-byte header:

typedef struct {
	char	id[4];	// 'DPAL'
	int		numcolors;
} header_t;

It is then followed by 'numcolors' 32-bit packed ARGB values.

The Dreamcast supports four different palette color formats, RGB565, ARGB1555
ARGB4444 and ARGB8888, but palette files are always saved in the ARGB8888
format. Your game can easily convert this to any other format before uploading
the palette to the PVR chip though. See the 'to16BPP' function if you need to
know how to do the conversion.
The reasoning behind always saving palettes as ARGB8888 is that the palette 
format setting is global, not per texture. So it makes sense to leave it up to
the game to decide which format to use. That way you can also switch formats
without having to reconvert your textures.



TWIDDLED TEXTURES
=================

For twiddled textures, the texels will be arranged in a way that is more cache
friendly. Adjacent texels will be closer to each other in memory compared to
textures stored in normal scan order. This increases rendering performance.
All textures (except for strided ones) output by the converter are twiddled.



STRIDED TEXTURES
================

Strided textures allow for the width of the texture to be any multiple of 32
from 32 to 992. The stride texture width is a global setting on the Dreamcast,
so all strided textures rendered in the same frame must have the same width.
They also cannot be twiddled, mipmapped or compressed, and cannot be used
with the bumpmap or paletted formats.

Since they cannot be twiddled, the rendering performance will also be lowered
for strided textures.

The texture width for strided textures will be set to the next power of two
size up while the actual size is divided by 32 and packed in the 'type' field.
This is because the width set in the polygon header must be a power of two.
So for a 320x256 texture you would get:
width = 512
height = 256
packed stride setting = 10 (320/32)

So basically, when loading a strided texture, set the width in the polygon
header to 'width' and set the global stride setting to the packed setting
in 'type'. 

You will also need to specify the U texture coordinate as if the texture
is actually 'width' wide.



COMPRESSED TEXTURES
===================

All textures (except strided ones) can be compressed using vector quantization.
This is a hardware feature on the Dreamcast and using compressed textures will
increase rendering performance at the possible cost of quality.

The compressed texture data always starts with a 2kB codebook followed by 
compressed index data. The codebook contains 256 blocks of texels. For 16-bit 
textures, each block represents 2x2 texels.

The codebook is followed by (width/blockwidth)x(height/blockheight) 8-bit
indices where each index refers to a block in the codebook. So if the first 
index is 35, it means that the top left 2x2 pixel block in the resulting
texture is block 35 in the codebook.

Compressed paletted textures work the same way except the blocks represent 4x4 
4-bit indices (for PAL4BPP) or 2x4 8-bit indices (for PAL8BPP). So there's an
extra level of lookup involved.