Mercurial > hg > dmlib
view tools/lib64gfx.h @ 2129:2129d4ac6f45
Refactor c64 image rendering completely to be more flexible.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 27 May 2019 11:29:37 +0300 |
parents | 56d4dc81774b |
children | 6528a1398e8e |
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 // Define default character ROM path #ifndef DM_DEF_CHARGEN #define DM_DEF_CHARGEN "/usr/local/lib64/vice/C64/chargen" #endif // 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_MAX_EXTRA_DATA 64 // 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_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 }; // 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[D64_SPR_HEIGHT_UT][D64_SPR_WIDTH_UT]; } DMC64Sprite; typedef struct _DMC64ImageCommonFormat DMC64ImageCommonFormat; typedef struct _DMC64ImageFormat DMC64ImageFormat; typedef struct _DMC64Image { DMC64ImageCommonFormat *fmt; int laceType, // Interlace type (D64_ILACE_*) nbanks; // Number of video banks used // 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[D64_MAX_EXTRA_DATA]; //DMC64Sprite sprites[D64_MAX_SPRITES]; } DMC64Image; 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 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); } DMC64EncDecOp; #define D64_MAX_ENCDEC_OPS 64 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 type, // 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 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[D64_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); int dmSetDefaultC64Palette(DMImage *img); int 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); 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 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); // // 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); // // 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; 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 const DMC64EncDecOp * fmtGetEncDecOp(const DMC64ImageFormat *fmt, const int index) { return &fmt->format->encdecOps[index]; } #ifdef __cplusplus } #endif #endif // LIB64GFX_H