view tools/lib64gfx.h @ 2576:812b16ee49db

I had been living under apparent false impression that "realfft.c" on which the FFT implementation in DMLIB was basically copied from was released in public domain at some point, but it could very well be that it never was. Correct license is (or seems to be) GNU GPL. Thus I removing the code from DMLIB, and profusely apologize to the author, Philip Van Baren. It was never my intention to distribute code based on his original work under a more liberal license than originally intended.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 11 Mar 2022 16:32:50 +0200
parents c6ee41fd98dd
children 9807ae37ad69
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-2021 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


// Max defines
#define D64_MAX_EXTRA_DATA     16  // Number of extraData slots
#define D64_MAX_EXTRA_INFO     64  // Number of extraInfo slots


// Bitmap constants
#define D64_SCR_WIDTH          320
#define D64_SCR_HEIGHT         200
#define D64_SCR_CH_WIDTH       (D64_SCR_WIDTH / 8)
#define D64_SCR_CH_HEIGHT      (D64_SCR_HEIGHT / 8)

// Full screen size with borders
#define D64_SCR_FULL_WIDTH     384
#define D64_SCR_FULL_HEIGHT    272

// Define the usually visible area
#define D64_SCR_MIN_XC         32
#define D64_SCR_MAX_XC         (D64_SCR_MIN_XC + D64_SCR_WIDTH)
#define D64_SCR_MIN_YC         50
#define D64_SCR_MAX_YC         (D64_SCR_MIN_YC + D64_SCR_HEIGHT)



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

// Sprite constants
#define D64_SPR_WIDTH_PX       24
#define D64_SPR_HEIGHT_PX      21
#define D64_SPR_WIDTH_UT       (D64_SPR_WIDTH_PX / 8) // bytes
#define D64_SPR_HEIGHT_UT      D64_SPR_HEIGHT_PX
#define D64_SPR_SIZE           ((D64_SPR_WIDTH_UT * D64_SPR_HEIGHT_UT) + 1)
#define D64_MAX_SPRITES        8 // Max sprites per scanline (in simple cases)


// Character constants
#define D64_CHR_WIDTH_PX       8
#define D64_CHR_HEIGHT_PX      8
#define D64_CHR_WIDTH_UT       1 // bytes
#define D64_CHR_HEIGHT_UT      8 // lines
#define D64_CHR_SIZE           (D64_CHR_WIDTH_UT * D64_CHR_HEIGHT_UT)

// Etc.
#define D64_NCOLORS            16
#define D64_VIDBANK_SIZE       (16*1024)
#define D64_MAX_CHARS          256


// Different supported flags/modes
enum
{
    D64_FMT_HIRES        = 0x000001, // Hi-res
    D64_FMT_MC           = 0x000002, // MultiColor
    D64_FMT_ECM          = 0x000003, // ECM mode (applies only to character mode)
    D64_FMT_MODE_MASK    = 0x00000f,

    D64_FMT_ILACE        = 0x000010, // Interlace
    D64_FMT_FLI          = 0x000020, // FLI
    D64_FMT_CHAR         = 0x000040, // Character mode
    D64_FMT_BORDER       = 0x000080, // Uses border area
    D64_FMT_SPRITES      = 0x000100, // Uses sprite layer

};


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


// Different types of interlace
enum
{
    D64_FLI_8            = 8,
};


// Various extra settings (see DMC64Image::extraInfo[])
enum
{
    D64_EI_MODE = 0,       // Actual mode, if the format supports several

    D64_EI_CHAR_CASE,      // [CHAR] 0 = upper case, != lower case
    D64_EI_CHAR_CUSTOM,    // [CHAR] 0 = ROM charset, != custom charset

    D64_EI_FLI_TYPE,       // FLI type (see D64_FLI_*)
    D64_EI_ILACE_TYPE,     // Interlace type (see D64_ILACE_*)
};


// 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 (DMC64EncDecOp::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_EXTRA_INFO,

    DS_LAST
};


// Operation flags (DMC64EncDecOp::flags)
enum
{
    DF_NORMAL            = 0xffffff,
    DF_DECODE            = 0x000001,
    DF_ENCODE	         = 0x000002,
};


// Sprite flags (DMC64Sprite::flags)
enum
{
    D64_SPRF_MC          = 0x000001,
    D64_SPRF_X_EXPAND    = 0x000002,
    D64_SPRF_Y_EXPAND    = 0x000004,
};


typedef struct
{
    char *name;
    char *desc;
    DMColor colors[D64_NCOLORS];
} DMC64Palette;


typedef struct
{
    DMPalette *pal;      // Use this palette custom palette if != NULL
    DMC64Palette *cpal;  // If DMC64ImageConvSpec::pal == NULL, use this C64 palette

/*
    // XXX These are not actually used yet (if ever)
    int dither;          // Dither mode (D64_DITH_*)
    BOOL aspect;         // Render using pixel aspectX/aspectY, FALSE = par=1:1
*/
} DMC64ImageConvSpec;


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


typedef struct
{
    int xc, yc;  // Sprite coordinates (XXX TODO: borders etc.)
    int flags;   // D64_SPRF_* flags
    int color;   // Color
    int sprnum;  // Physical sprite number for priority checking

    Uint8 *data; // "const" pointer to sprite data, do not deallocate
} DMC64Sprite;


typedef struct _DMC64ImageCommonFormat DMC64ImageCommonFormat;
typedef struct _DMC64ImageFormat DMC64ImageFormat;


typedef struct _DMC64Image
{
    DMC64ImageCommonFormat *fmt;
    int nblocks; // Number of internal blocks used

    // Bitmaps, color RAM, screen, etc. blocks * nblocks
    // 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[D64_MAX_EXTRA_DATA];

    // Extra information / settings
    // See D64_EI_* constants.
    int extraInfo[D64_MAX_EXTRA_INFO];
} DMC64Image;


typedef struct
{
    Uint8 *col;
} DMC64ScanLine;


typedef int (*DMC64GetPixelFunc)(DMC64ScanLine *scan,
    const DMC64Image *img, const int rasterX, const int rasterY);


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

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

    int (*decFunction)(const struct _DMC64EncDecOp *op, DMC64Image *img, const DMGrowBuf *buf, const DMC64ImageCommonFormat *fmt);
    int (*encFunction)(const struct _DMC64EncDecOp *op, DMGrowBuf *buf, const DMC64Image *img, const DMC64ImageCommonFormat *fmt);

    int   flags;     // Operation flags (DF_*)
} DMC64EncDecOp;


#define D64_MAX_ENCDEC_OPS 32
typedef DMC64EncDecOp DMC64EncDecOpList[D64_MAX_ENCDEC_OPS];


typedef struct _DMC64ImageCommonFormat
{
    int  mode,               // Format mode/type flags, see D64_FMT_*
         width, height,      // Width and height in pixels
         chWidth, chHeight,  // Width and height in charblocks
         aspectX, aspectY;   // Pixel aspectX/Y (x=2 for multicolor, y=1 always)

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

    DMC64GetPixelFunc getPixel;

    DMC64EncDecOpList encdecOps;
} DMC64ImageCommonFormat;


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

    ssize_t addr;  // Loading address ( -2 if no loading address, -1 if loading address not known)
    size_t size;   // Size, including loading address. Only used in probing and encoding.
    size_t extra;  // Extra data used for some formats

    int  flags;    // DM_FMT_* flags (read/write/broken/etc.), 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
//
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
};


// Compression flags
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        = 0x000f,

    DM_RLE_ORDER_1          = 0x0010, // Order: <marker>, <count/run length>, <data>
    DM_RLE_ORDER_2          = 0x0020, // 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;
    size_t cropOutLen;
    int type;                // DM_COMP_*
    int flags;               //

    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 DMC64ImageFormat  dmC64ImageFormats[];
extern const int         ndmC64ImageFormats;
extern DMC64ImageFormat  **dmC64ImageFormatsSorted;


//
// Library init/close
//
int       dmLib64GFXInit(void);
void      dmLib64GFXClose(void);


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

int       dmC64PaletteFromC64Palette(DMPalette **ppal, const DMC64Palette *cpal, const BOOL mixed);
int       dmC64SetImagePalette(DMImage *img, const DMC64ImageConvSpec *spec, const BOOL mixed);

BOOL      dmCompareAddr16(const DMGrowBuf *buf, const size_t offs, const Uint16 addr);

int       dmC64MemBlockAlloc(DMC64MemBlock *blk, const size_t size);
int       dmC64MemBlockCopy(DMC64MemBlock *dst, const DMC64MemBlock *src);
void      dmC64MemBlockFree(DMC64MemBlock *blk);

// C64 bitmap image allocation/freeing
DMC64Image *dmC64ImageAlloc(const DMC64ImageFormat *fmt);
void      dmC64ImageFree(DMC64Image *img);


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

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

size_t    dmC64GetSubjectSize(const int subject, const DMC64ImageCommonFormat *fmt);
size_t    dmC64GetOpSubjectSize(const DMC64EncDecOp *op, const DMC64ImageCommonFormat *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 DMC64ImageConvSpec *spec);
int       dmC64ConvertImage2BMP(DMC64Image **pdst, const DMImage *src, const DMC64ImageFormat *fmt, const DMC64ImageConvSpec *spec);

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

int       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);


//
// Macros for defining variables used in getpixel functions
//
#define DM_C64_GENERIC_SC_PIXEL_DEFS(ximg) \
    const int \
        x = rasterX / 8, \
        y = rasterY / 8, \
        yb = rasterY & 7, \
        yoffs = y * ximg->fmt->chWidth, \
        bmoffs = yoffs * 8 + yb + (x * 8), \
        scroffs = yoffs + x, \
        vshift = 7 - (rasterX & 7);


#define DM_C64_GENERIC_MC_PIXEL_DEFS(ximg) \
    const int \
        x = rasterX / 4, \
        y = rasterY / 8, \
        yb = rasterY & 7, \
        yoffs = y * (ximg)->fmt->chWidth, \
        bmoffs = yoffs * 8 + yb + (x * 8), \
        scroffs = yoffs + x, \
        vshift = 6 - ((rasterX * 2) & 6);


#define DM_C64_GENERIC_CHAR_PIXEL(ximg) \
    const int \
        x = rasterX / 8, \
        y = rasterY / 8, \
        scroffs = y * (ximg)->fmt->chWidth + x; \


//
// Pixel format helpers
//
int dmC64GetGenericSCPixel(Uint8 *col,
    const DMC64Image *img, const int bmoffs, const int scroffs,
    const int vshift, const int vbank, const int bitmap);

int dmC64GetGenericMCPixel(Uint8 *col,
    const DMC64Image *img, const int bmoffs, const int scroffs,
    const int vshift, const int vbank, const int bitmap,
    const int cbank, const int bgcolor);

int dmC64GetGenericCharSCPixel(Uint8 *col,
    const DMC64Image *img, const int scroffs, const int rasterX,
    const int chrbank, const size_t chroffs, const int chr,
    const int cbank, const int bgcolor);

int dmC64GetGenericCharMCPixel(Uint8 *col,
    const DMC64Image *img, const int scroffs, const int rasterX,
    const int chrbank, const size_t chroffs, const int chr,
    const int cbank, const int bgcolor,
    const int bgd022, const int bgd023);

int dmC64GetGenericCharECMPixel(Uint8 *col,
    const DMC64Image *img, const int scroffs, const int rasterX,
    const int chrbank, const size_t chroffs, const int chr,
    const int cbank, const int bgcolor,
    const int bgd022, const int bgd023, const int bgd024);


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


#ifdef __cplusplus
}
#endif

#endif // LIB64GFX_H