view tools/lib64gfx.h @ 1931:410679d2fe8a

"Enable" the image->c64 bitmap conversion path in gfxconv. It does not work without the necessary bits elsewhere, though. Also add DMC64ImageConvSpec structure for delivering conversion parameters, though it is not yet used either.
author Matti Hamalainen <ccr@tnsp.org>
date Thu, 28 Jun 2018 17:26:30 +0300
parents 42cd527a01b9
children 10e82be38b8b
line wrap: on
line source

/*
 * Functions for reading and converting various restricted
 * C64/etc and/or indexed/paletted graphics formats.
 * Programmed and designed by Matti 'ccr' Hamalainen
 * (C) Copyright 2012-2018 Tecnic Software productions (TNSP)
 *
 * Please read file 'COPYING' for information on license and distribution.
 */
#ifndef LIB64GFX_H
#define LIB64GFX_H 1

#include "libgfx.h"
#include "dmgrowbuf.h"

#ifdef __cplusplus
extern "C" {
#endif


// Bitmap constants
#define C64_SCR_WIDTH          320
#define C64_SCR_HEIGHT         200
#define C64_SCR_CH_WIDTH       (C64_SCR_WIDTH/8)
#define C64_SCR_CH_HEIGHT      (C64_SCR_HEIGHT/8)
#define C64_MAX_EXTRA_DATA     64

// C64 video screen pixel aspect ratio on PAL
#define C64_SCR_PAR_XY         (0.9365f)

// Sprite constants
#define C64_SPR_WIDTH_PX       24
#define C64_SPR_HEIGHT_PX      21
#define C64_SPR_WIDTH_UT       (C64_SPR_WIDTH_PX / 8) // bytes
#define C64_SPR_HEIGHT_UT      C64_SPR_HEIGHT_PX
#define C64_SPR_SIZE           ((C64_SPR_WIDTH_UT * C64_SPR_HEIGHT_UT) + 1)

// Character constants
#define C64_CHR_WIDTH_PX       8
#define C64_CHR_HEIGHT_PX      8
#define C64_CHR_WIDTH_UT       1 // bytes
#define C64_CHR_HEIGHT_UT      8 // lines
#define C64_CHR_SIZE           (C64_CHR_WIDTH_UT * C64_CHR_HEIGHT_UT)

// Etc.
#define C64_NCOLORS            16
#define C64_VIDBANK_SIZE       (16*1024)
#define C64_MAX_SPRITES        1024
#define C64_MAX_CHARS          256


// Different supported flags/modes
enum
{
    D64_FMT_HIRES        = 0x0000, // Hi-res
    D64_FMT_MC           = 0x0001, // MultiColor
    D64_FMT_ILACE        = 0x0002, // Interlace
    D64_FMT_FLI          = 0x0004, // FLI
    D64_FMT_CHAR         = 0x0008, // Character mode
    D64_FMT_BORDER       = 0x0010, // Uses border area
};


// Different types of interlace
enum
{
    D64_ILACE_NONE       = 0x0000, // Not set (invalid for interlaced images)
    D64_ILACE_RES        = 0x0001, // Interlace doubles resolution
    D64_ILACE_COLOR      = 0x0002, // Uses color mixing
};


// Charmode screen memory configuration
enum
{
    D64_CHCFG_SCREEN,      // Use screen memory
    D64_CHCFG_LINEAR = 1,  // Generate linear pattern so that first line
                           // of chars is 0-39, second 40-79, up to 255.
};


// Image <-> bitmap conversion dithering
enum
{
    D64_DITH_NONE = 0,     // No dithering
};


// Different enc/dec operation types (op->type)
enum
{
    DO_COPY,               // Perform copy between memory (from/to offset) and subject
    DO_SET_MEM,            // Set subject value or fill subject memory area to byte value from offset
    DO_SET_OP,             // Like above but value from op->offs field instead

    DO_SET_MEM_HI,         // Copy one byte value like DO_SET_MEM, but high nibble only
    DO_SET_MEM_LO,         // Like above, but low nibble

    DO_FUNC,               // Execute specified decoding / encoding function

    DO_CHAR_CFG,           // Set character mode configuration

    DO_LAST,               // Last opcode, end processing
};


// "Subjects" of operations (op->subject)
enum
{
    DS_COLOR_RAM,
    DS_BITMAP_RAM,
    DS_SCREEN_RAM,
    DS_EXTRA_DATA,
    DS_CHAR_DATA,

    DS_D020,
    DS_BGCOL,
    DS_D021,
    DS_D022,
    DS_D023,
    DS_D024,

    DS_LAST
};


typedef struct
{
    int dither;      // Dither mode (D64_DITH_*)
    BOOL aspect;     // Correct pixel aspect ratio?
} DMC64ImageConvSpec;


typedef struct
{
    Uint8 *data;
    size_t size;
} DMC64MemBlock;


typedef struct
{
    BOOL multicolor, xexpand, yexpand;
    int color, xc, yc;
    Uint8 data[C64_SPR_HEIGHT_UT][C64_SPR_WIDTH_UT];
} DMC64Sprite;


typedef struct _DMC64Image
{
    int type,       // Image type (D64_FMT_*)
        laceType,   // Interlace type (D64_ILACE_*)
        nbanks;

    int width, height; // Width and height in pixels
    int chWidth, chHeight; // Width and height in charblocks

    // Bitmaps, color RAM, screen, etc. blocks * nbanks
    // Not all of them may be allocated
    DMC64MemBlock
        *color,
        *bitmap,
        *screen,
        *charData;

    // Other standard colours
    Uint8 d020, bgcolor, d022, d023, d024;

    // Extra data areas used by some formats,
    // for example raster colours might be stored
    DMC64MemBlock extraData[C64_MAX_EXTRA_DATA];

    DMC64Sprite sprites[C64_MAX_SPRITES];
} DMC64Image;


typedef Uint8 (*DMC64GetPixelFunc)(
    const DMC64Image *img, const int bmoffs, const int scroffs,
    const int vshift, const int vbitmap, const int rasterX, const int rasterY);

#define D64_MAX_ENCDEC_OPS 64


typedef struct _DMC64ImageFormat DMC64ImageFormat;


typedef struct _DMC64EncDecOp
{
    int    type;     // Operation type (DO_*)
    int    subject;  // Operation "subject" (DS_*)

    size_t offs;     // Offset in "memory"
    int    bank;     // Bank number or extradata index
    size_t size;     // Size of data (0 for "default")
    size_t offs2;    // Offset in data-block

    BOOL   (*decFunction)(DMC64Image *img, const struct _DMC64EncDecOp *op, const DMGrowBuf *buf, const DMC64ImageFormat *fmt);
    BOOL   (*encFunction)(const struct _DMC64EncDecOp *op, DMGrowBuf *buf, const DMC64Image *img, const DMC64ImageFormat *fmt);
} DMC64EncDecOp;


typedef DMC64EncDecOp DMC64EncDecOpList[D64_MAX_ENCDEC_OPS];


typedef struct
{
    int  type;   // Type flags, see D64_FMT_*
    int  width, height; // Width and height in pixels
    int  chWidth, chHeight; // Width and height in charblocks

    int  (*convertFrom)(DMImage *, const DMC64Image *, const DMC64ImageFormat *fmt, const DMC64ImageConvSpec *spec);
    int  (*convertTo)(DMC64Image *, const DMImage *, const DMC64ImageFormat *fmt, const DMC64ImageConvSpec *spec);

    DMC64GetPixelFunc getPixel;

    DMC64EncDecOpList encdecOps;
} DMC64ImageCommonFormat;


typedef struct _DMC64ImageFormat
{
    char *fext;  // Filename extension
    char *name;  // Format description/name

    size_t addr; // Loading address (0 if no loading address)
    size_t size; // Size, including loading address. Only used in probing and encoding.

    int  flags;  // DM_FMT_* flags, see libgfx.h

    int  (*probe)(const DMGrowBuf *buf, const DMC64ImageFormat *fmt);

    int  (*decode)(DMC64Image *img, const DMGrowBuf *buf, const DMC64ImageFormat *fmt);
    int  (*encode)(DMGrowBuf *buf, const DMC64Image *img, const DMC64ImageFormat *fmt);

    DMC64ImageCommonFormat formatDef, *format;
} DMC64ImageFormat;


//
// Compression types and flags
//
enum
{
    DM_COMP_RLE_MARKER      = 1, // RLE with a separate marker byte
    DM_COMP_RLE_MASK        = 2, // RLE that has marker bits and lower part acts as run length
};

enum
{
    DM_RLE_BYTE_RUNS        = 0x0001, // Uses one-byte run lengths
    DM_RLE_WORD_RUNS        = 0x0002, // Uses two-byte (word) run lengths
    DM_RLE_RUNS_MASK        = 0x0003,

    DM_RLE_ORDER_1          = 0x0000, // Order: <marker>, <count/run length>, <data>
    DM_RLE_ORDER_2          = 0x0010, // Order: <marker>, <data>, <count/run length>
    DM_RLE_ORDER_MASK       = 0x00f0,

    DM_RLE_BACKWARDS_INPUT  = 0x0100, // Input is read backwards
    DM_RLE_BACKWARDS_OUTPUT = 0x0200, // Output is written backwards
    DM_RLE_ZERO_COUNT_MAX   = 0x0400, // Zero "count" / run length value is max run (2^8, 2^16)

    DM_OUT_CROP_NONE        = 0x0000,
    DM_OUT_CROP_START       = 0x1000,
    DM_OUT_CROP_END         = 0x2000,
    DM_OUT_CROP_MASK        = 0xf000,
};


typedef struct
{
    char *func;
    int type;
    int flags;
    size_t cropOutLen;

    Uint8
        // DM_COMP_RLE_MARKER mode
        rleMarkerB,          // Marker byte for byte length runs (if DM_RLE_BYTE_RUNS used)
        rleMarkerW,          // Marker byte for word length runs (if DM_RLE_WORD_RUNS used)

        // DM_COMP_RLE_MASK mode
        rleMarkerBits,
        rleMarkerMask,       // Mask bits for marker: data & rleMarkerMask == rleMarkerBits
        rleCountMask;        // Mask bits for length: count = data & rleCountMask

    unsigned int
        // Minimum and maximum run lengths
        rleMinCountB,
        rleMinCountW,
        rleMaxCountB,
        rleMaxCountW;
} DMCompParams;


//
// Global variables
//
extern DMColor           dmDefaultC64Palette[C64_NCOLORS];
extern DMC64ImageFormat  dmC64ImageFormats[];
extern const int         ndmC64ImageFormats;


//
// Miscellaneous functions
//
void      dmC64InitializeFormats(void);
int       dmC64ProbeBMP(const DMGrowBuf *buf, const DMC64ImageFormat **fmt);

char *    dmC64GetImageTypeString(char *buf, const size_t len, const int type, const BOOL lng);
void      dmC64ImageDump(FILE *fh, const DMC64Image *img, const DMC64ImageFormat *fmt, const char *indent);

void      dmSetDefaultC64Palette(DMImage *img);
BOOL      dmSetMixedColorC64Palette(DMImage *img);

BOOL      dmCompareAddr16(const DMGrowBuf *buf, const size_t offs, const Uint16 addr);
int       dmC64ImageGetNumBanks(const DMC64ImageFormat *fmt);

// C64 bitmap image allocation/freeing
int       dmC64MemBlockAlloc(DMC64MemBlock *blk, const size_t size);
int       dmC64MemBlockCopy(DMC64MemBlock *dst, const DMC64MemBlock *src);
void      dmC64MemBlockFree(DMC64MemBlock *blk);

DMC64Image *dmC64ImageAlloc(const DMC64ImageFormat *fmt);
void      dmC64ImageFree(DMC64Image *img);


// Encoding and decoding of formats and images
int       dmC64ConvertCSDataToImage(DMImage *img, int xoffs, int yoffs, const Uint8 *inBuf, int width, int height, BOOL multicolor, int *colors);

const char *dmC64GetOpSubjectName(const int subject);
void      dmC64GetOpMemBlock(const DMC64Image *img, const int subject, const int bank, const DMC64MemBlock **blk);
int       dmC64SanityCheckEncDecOp(const int i, const DMC64EncDecOp *op, const DMC64Image *img);

size_t    dmC64GetSubjectSize(const int subject, const DMC64ImageFormat *fmt);
size_t    dmC64GetOpSubjectSize(const DMC64EncDecOp *op, const DMC64ImageFormat *fmt);


int       dmC64DecodeGenericBMP(DMC64Image *img, const DMGrowBuf *buf, const DMC64ImageFormat *fmt);
int       dmC64EncodeGenericBMP(const BOOL allocate, DMGrowBuf *buf, const DMC64Image *img, const DMC64ImageFormat *fmt);

int       dmC64ConvertBMP2Image(DMImage **pdst, const DMC64Image *src, const DMC64ImageFormat *fmt, const DMC64ImageConvSpec *spec);
int       dmC64ConvertImage2BMP(DMC64Image **pdst, const DMImage *src, const DMC64ImageFormat *fmt, const DMC64ImageConvSpec *spec);

int       dmC64DecodeBMP(DMC64Image **img, const DMGrowBuf *buf, const size_t probeOffs, const size_t loadOffs, const DMC64ImageFormat **fmt, const DMC64ImageFormat *forced);
int       dmC64EncodeBMP(DMGrowBuf *buf, const DMC64Image *img, const DMC64ImageFormat *fmt);

int       dmC64ConvertGenericBMP2Image(DMImage *dst, const DMC64Image *src, const DMC64ImageFormat *fmt, const DMC64ImageConvSpec *spec);
int       dmC64ConvertGenericImage2BMP(DMC64Image *dst, const DMImage *src, const DMC64ImageFormat *fmt, const DMC64ImageConvSpec *spec);

void      dmGenericRLEAnalyze(const DMGrowBuf *buf, DMCompParams *cfg);

void      dmSetupRLEBuffers(DMGrowBuf *dst, DMGrowBuf *src, const DMCompParams *cfg);
void      dmFinishRLEBuffers(DMGrowBuf *dst, DMGrowBuf *src, const DMCompParams *cfg);

int       dmGenericRLEOutputRun(DMGrowBuf *dst, const DMCompParams *cfg, const Uint8 data, const unsigned int count);
int       dmEncodeGenericRLESequence(DMGrowBuf *dst, const Uint8 data, const unsigned int count, const DMCompParams *cfg);

int       dmDecodeGenericRLE(DMGrowBuf *dst, const DMGrowBuf *src, const DMCompParams *cfg);
int       dmDecodeGenericRLEAlloc(DMGrowBuf *dst, const DMGrowBuf *src, const DMCompParams *cfg);

int       dmEncodeGenericRLE(DMGrowBuf *dst, const DMGrowBuf *src, const DMCompParams *cfg);
int       dmEncodeGenericRLEAlloc(DMGrowBuf *dst, const DMGrowBuf *src, const DMCompParams *cfg);


//
// Inline helper functions for pixel format decoding
//
static inline Uint8 dmC64GetGenericSCPixel(
    const DMC64Image *img, const int bmoffs, const int scroffs,
    const int vshift, const int vbank, const int vbitmap, const int cbank)
{
    (void) cbank;
    if ((img->bitmap[vbitmap].data[bmoffs] >> vshift) & 1)
        return img->screen[vbank].data[scroffs] >> 4;
    else
        return img->screen[vbank].data[scroffs] & 15;
}


static inline Uint8 dmC64GetGenericMCPixel(
    const DMC64Image *img, const int bmoffs, const int scroffs,
    const int vshift, const int vbank, const int vbitmap, const int cbank, const int bgcolor)
{
    switch ((img->bitmap[vbitmap].data[bmoffs] >> vshift) & 3)
    {
        case  0: return bgcolor;
        case  1: return img->screen[vbank].data[scroffs] >> 4;
        case  2: return img->screen[vbank].data[scroffs] & 15;
        default: return img->color[cbank].data[scroffs] & 15;
    }
}


static inline Uint8 fmtGetGenericSCPixel(
    const DMC64Image *img, const int bmoffs, const int scroffs,
    const int vshift, const int vbitmap, const int rasterX, const int rasterY)
{
    (void) rasterX;
    (void) rasterY;
    return dmC64GetGenericSCPixel(img, bmoffs, scroffs, vshift, 0, vbitmap, 0);
}


static inline Uint8 fmtGetGenericMCPixel(
    const DMC64Image *img, const int bmoffs, const int scroffs,
    const int vshift, const int vbitmap, const int rasterX, const int rasterY)
{
    (void) rasterX;
    (void) rasterY;
    return dmC64GetGenericMCPixel(img, bmoffs, scroffs, vshift, 0, vbitmap, 0, img->bgcolor);
}


static inline const DMC64EncDecOp * fmtGetEncDecOp(const DMC64ImageFormat *fmt, const int index)
{
    return &fmt->format->encdecOps[index];
}


#ifdef __cplusplus
}
#endif

#endif // LIB64GFX_H