Mercurial > hg > dmlib
view tools/lib64gfx.h @ 2296:732fa926a5ef
Constify.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 04 Jul 2019 10:50:07 +0300 |
parents | ecc17b2e129e |
children | e798a41f27a5 |
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-2019 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 #define D64_MAX_EXTRA_INFO 64 // 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) #define D64_SCR_FULL_WIDTH 384 #define D64_SCR_FULL_HEIGHT 272 #define D64_SCR_VIS_XOFFS 24 #define D64_SCR_VIS_YOFFS 50 // 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) // 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_SPRITES 1024 #define D64_MAX_CHARS 256 // Different supported flags/modes enum { D64_FMT_HIRES = 0x0001, // Hi-res D64_FMT_MC = 0x0002, // MultiColor D64_FMT_ECM = 0x0003, // ECM mode (applies only to character mode) D64_FMT_MODE_MASK = 0x000f, D64_FMT_ILACE = 0x0010, // Interlace D64_FMT_FLI = 0x0020, // FLI D64_FMT_CHAR = 0x0040, // Character mode D64_FMT_BORDER = 0x0080, // 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 }; // Different types of interlace enum { D64_FLI_8 = 8, }; // 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. }; // Various extra settings (see DMC64Image::extraInfo[]) enum { D64_EI_MODE = 0, // Actual mode, if the format supports several D64_EI_CHAR_CASE, D64_EI_CHAR_CUSTOM, D64_EI_FLI_TYPE, D64_EI_ILACE_TYPE, }; // 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_EXTRA_INFO, DS_LAST }; // Operation flags (op->flags) enum { DF_NORMAL = 0xffff, DF_DECODE = 0x0001, DF_ENCODE = 0x0002, }; typedef struct { char *name; char *desc; DMColor colors[D64_NCOLORS]; } DMC64Palette; typedef struct { int dither; // Dither mode (D64_DITH_*) BOOL aspect; // Correct pixel aspect ratio? DMPalette *pal; // Use this palette DMC64Palette *cpal; // If ^pal == NULL, use this C64 palette } DMC64ImageConvSpec; typedef struct { Uint8 *data; size_t size; } DMC64MemBlock; typedef struct { BOOL multicolor, xexpand, yexpand; int color, xc, yc; Uint8 data[D64_SPR_HEIGHT_UT][D64_SPR_WIDTH_UT]; } 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 used by some formats, // for example some PETSCII-type formats. // See D64_EI_* constants. int extraInfo[D64_MAX_EXTRA_INFO]; //DMC64Sprite sprites[D64_MAX_SPRITES]; } DMC64Image; 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 offs2; // 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 int (*DMC64GetPixelFunc)(Uint8 *col, const DMC64Image *img, const int rasterX, const int rasterY); 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 int (*convertFrom)(DMImage *, const DMC64Image *, 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 (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 DMC64Palette dmC64DefaultPalettes[]; extern const int ndmC64DefaultPalettes; 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, int xoffs, int yoffs, const Uint8 *inBuf, int width, int height, BOOL multicolor, int *colors); int dmC64ImageGetNumBlocks(const DMC64ImageFormat *fmt); 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, 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 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); // // Macros for defining variables used in getpixel functions // #define DM_C64_GENERIC_SC_PIXEL_DEFS(ximg) \ const int \ x = rasterX / 8, \ y = rasterY / 8, \ yoffs = y * ximg->fmt->chWidth, \ bmoffs = yoffs * 8 + (rasterY & 7) + (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, \ yoffs = y * (ximg)->fmt->chWidth, \ bmoffs = yoffs * 8 + (rasterY & 7) + (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; \ // // Inline helper functions for pixel format decoding // static inline int dmC64GetGenericSCPixel(Uint8 *col, const DMC64Image *img, const int bmoffs, const int scroffs, const int vshift, const int vbank, const int bitmap) { if ((img->bitmap[bitmap].data[bmoffs] >> vshift) & 1) *col = img->screen[vbank].data[scroffs] >> 4; else *col = img->screen[vbank].data[scroffs] & 15; return DMERR_OK; } static inline 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) { switch ((img->bitmap[bitmap].data[bmoffs] >> vshift) & 3) { case 0: *col = bgcolor & 15; break; case 1: *col = img->screen[vbank].data[scroffs] >> 4; break; case 2: *col = img->screen[vbank].data[scroffs] & 15; break; default: *col = img->color[cbank].data[scroffs] & 15; break; } return DMERR_OK; } static inline 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) { if (chroffs >= img->charData[chrbank].size) { return dmError(DMERR_INVALID_DATA, "Character map index #%d out of bounds for char ROM data.\n", chr); } const int vshift = 7 - (rasterX & 7); if ((img->charData[chrbank].data[chroffs] >> vshift) & 1) *col = img->color[cbank].data[scroffs] & 15; else *col = bgcolor & 15; return DMERR_OK; } static inline 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) { if (chroffs >= img->charData[chrbank].size) { return dmError(DMERR_INVALID_DATA, "Character map index #%d out of bounds for char ROM data.\n", chr); } const int ccol = img->color[cbank].data[scroffs]; if (ccol & 8) { const int vshift = 6 - (rasterX & 6); switch ((img->charData[chrbank].data[chroffs] >> vshift) & 3) { case 0: *col = bgcolor & 15; break; case 1: *col = bgd022 & 15; break; case 2: *col = bgd023 & 15; break; case 3: *col = ccol & 7; } } else { const int vshift = 7 - (rasterX & 7); if ((img->charData[chrbank].data[chroffs] >> vshift) & 1) *col = ccol & 7; else *col = bgcolor & 15; } return DMERR_OK; } static inline 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) { if (chroffs >= img->charData[0].size) { return dmError(DMERR_INVALID_DATA, "Character map index #%d out of bounds for char ROM data.\n", chr); } const int vshift = 7 - (rasterX & 7); if ((img->charData[chrbank].data[chroffs] >> vshift) & 1) *col = img->color[cbank].data[scroffs] & 15; else switch ((chr >> 6) & 3) { case 0: *col = bgcolor & 15; break; case 1: *col = bgd022 & 15; break; case 2: *col = bgd023 & 15; break; case 3: *col = bgd024 & 15; break; } return DMERR_OK; } static inline const DMC64EncDecOp * fmtGetEncDecOp(const DMC64ImageFormat *fmt, const int index) { return &fmt->format->encdecOps[index]; } #ifdef __cplusplus } #endif #endif // LIB64GFX_H