Mercurial > hg > dmlib
changeset 931:2270d7f3af77
Refactor the DMC64Image handling to be more dynamic, and start
work on allowing non 320/160 x 200 formats, and charmode based formats.
There is still work to be done, and some problems to sort out.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Wed, 25 Feb 2015 19:37:59 +0200 |
parents | efbad8817b79 |
children | 6320bf08e302 |
files | tools/gfxconv.c tools/lib64gfx.c tools/lib64gfx.h tools/view64.c |
diffstat | 4 files changed, 179 insertions(+), 85 deletions(-) [+] |
line wrap: on
line diff
--- a/tools/gfxconv.c Wed Feb 25 19:32:55 2015 +0200 +++ b/tools/gfxconv.c Wed Feb 25 19:37:59 2015 +0200 @@ -1556,7 +1556,7 @@ { FILE *inFile; const DMC64ImageFormat *cfmt; - DMC64Image cimage; + DMC64Image *cimage = NULL; Uint8 *dataBuf = NULL; size_t dataSize; int i; @@ -1709,7 +1709,7 @@ switch (optOutFormat) { case FFMT_IMAGE: - res = dmC64ConvertBMP2Image(&outImage, &cimage, cfmt, FALSE); + res = dmC64ConvertBMP2Image(&outImage, cimage, cfmt, FALSE); if (res != DMERR_OK || outImage == NULL) { @@ -1722,12 +1722,12 @@ case FFMT_BITMAP: - res = dmWriteBitmap(optOutFilename, &cimage, optOutSubFormat, TRUE); + res = dmWriteBitmap(optOutFilename, cimage, optOutSubFormat, TRUE); break; case FFMT_CHAR: case FFMT_SPRITE: - res = dmC64ConvertBMP2Image(&outImage, &cimage, cfmt, TRUE); + res = dmC64ConvertBMP2Image(&outImage, cimage, cfmt, TRUE); if (res != DMERR_OK || outImage == NULL) { @@ -1803,6 +1803,7 @@ error: dmFree(dataBuf); + dmFree(cimage); return -3; exit(3); }
--- a/tools/lib64gfx.c Wed Feb 25 19:32:55 2015 +0200 +++ b/tools/lib64gfx.c Wed Feb 25 19:37:59 2015 +0200 @@ -12,6 +12,59 @@ #define BUF_SIZE_GROW (4*1024) +DMC64Image * dmC64ImageAlloc(int width, int height, int ch_width, int ch_height) +{ + int i; + DMC64Image *img = dmMalloc0(sizeof(DMC64Image)); + + if (img == NULL) + return NULL; + + img->width = width; + img->height = height; + img->ch_width = ch_width; + img->ch_height = ch_height; + + for (i = 0; i < C64_SCR_MAX_BANK; i++) + { + if ((img->color[i] = dmMalloc0(ch_width * ch_height)) == NULL) + goto err; + + if ((img->bitmap[i] = dmMalloc0(ch_width * ch_height * 8)) == NULL) + goto err; + + if ((img->screen[i] = dmMalloc0(ch_width * ch_height)) == NULL) + goto err; + + if ((img->charmem[i] = dmMalloc0(C64_MAX_CHARS * C64_CHR_SIZE)) == NULL) + goto err; + } + + return img; + +err: + dmC64ImageFree(img); + return NULL; +} + + +void dmC64ImageFree(DMC64Image *img) +{ + if (img != NULL) + { + int i; + for (i = 0; i < C64_SCR_MAX_BANK; i++) + { + dmFree(img->color[i]); + dmFree(img->bitmap[i]); + dmFree(img->screen[i]); + } + memset(img, 0, sizeof(DMC64Image)); + dmFree(img); + } +} + + char * dmC64GetImageTypeString(char *buf, const size_t len, const int type) { *buf = 0; @@ -519,13 +572,11 @@ } }, -#define XX2_WIDTH_CH 40 -#define XX2_HEIGHT_CH 10 +#define XX2_WIDTH_CH 40 +#define XX2_HEIGHT_CH 10 +#define XX2_SIZE (XX2_WIDTH_CH * XX2_HEIGHT_CH) +#define XX2_BSIZE (XX2_SIZE * 8) -#define XX2_SIZE (XX2_WIDTH_CH * XX2_HEIGHT_CH) -#define XX2_BSIZE (XX2_SIZE * 8) - -#if 0 { D64_FMT_MC, "xx2", "Unknown $2000 format (unpacked)", 0x2000, 4002, XX2_WIDTH_CH * 4, XX2_HEIGHT_CH * 8, @@ -542,20 +593,19 @@ } }, -#else - +#if 0 { - D64_FMT_MC | D64_FMT_CHAR, "xx2", "Unknown $2000 char format (unpacked)", 0x2000, 4002, - XX2_WIDTH_CH * 4, XX2_HEIGHT_CH * 8, - XX2_WIDTH_CH , XX2_HEIGHT_CH, + D64_FMT_MC | D64_FMT_CHAR, "xx3", "??? (unpacked)", 0x2000, 0, + XX3_WIDTH_CH * 4, XX3_HEIGHT_CH * 8, + XX3_WIDTH_CH , XX3_HEIGHT_CH, NULL, NULL, NULL, NULL, NULL, 4, { - { DT_CHAR_DATA, 0x0000, 0, XX2_BSIZE, NULL, NULL }, - { DT_COLOR_RAM, XX2_BSIZE + XX2_SIZE , 0, XX2_SIZE, NULL, NULL }, + { DT_CHAR_DATA, 0x0000, 0, XX3_BSIZE, NULL, NULL }, + { DT_COLOR_RAM, XX3_BSIZE + XX3_SIZE , 0, XX3_SIZE, NULL, NULL }, - { DT_CHAR_CONFIG, D64_CHCFG_LINEAR, 0, XX2_SIZE, NULL, NULL }, + { DT_CHAR_CONFIG, D64_CHCFG_LINEAR, 0, XX3_SIZE, NULL, NULL }, { DT_COLOR_SET, 1 , 0, DC_BGCOL, NULL, NULL }, { DT_COLOR_SET, 3 , 0, DC_D022, NULL, NULL }, { DT_COLOR_SET, 4 , 0, DC_D023, NULL, NULL }, @@ -625,34 +675,51 @@ } -static int dmC64GetOpSize(const DMC64EncDecOp *op, const DMC64ImageFormat *fmt) +static BOOL dmC64GetOpSize(const DMC64EncDecOp *op, const DMC64ImageFormat *fmt, size_t *size) { - if (op->size != 0) - return op->size; - + BOOL check; switch (op->type) { case DT_SCREEN_RAM: - return C64_SCREEN_SIZE; - case DT_COLOR_RAM: - return C64_COLOR_SIZE; + *size = fmt->ch_height * fmt->ch_width; + check = TRUE; + break; case DT_BITMAP: - return C64_BITMAP_SIZE; + *size = fmt->ch_height * fmt->ch_width * 8; + check = TRUE; + break; case DT_EXTRADATA: - return C64_SCR_EXTRADATA; + *size = C64_SCR_EXTRADATA; + check = TRUE; + break; case DT_CHAR_DATA: - return C64_MAX_CHARS * C64_CHR_HEIGHT * C64_CHR_WIDTH; + *size = C64_MAX_CHARS * C64_CHR_SIZE; + check = TRUE; + break; case DT_COLOR_REG: - return 1; + *size = 1; + check = FALSE; + break; default: - return 0; + *size = 0; + check = FALSE; } + + if (op->size != 0) + { + if (check && op->size > *size) + return FALSE; + + *size = op->size; + } + + return TRUE; } @@ -671,8 +738,11 @@ } // Clear the image structure, set basics - memset(img, 0, sizeof(*img)); - img->type = fmt->type; + img->type = fmt->type; + img->width = fmt->width; + img->height = fmt->height; + img->ch_width = fmt->ch_width; + img->ch_height = fmt->ch_height; // Perform decoding for (i = 0; i < fmt->nencdecOps; i++) @@ -687,7 +757,13 @@ return res; // Check size - size = dmC64GetOpSize(op, fmt); + if (!dmC64GetOpSize(op, fmt, &size)) + { + dmError("Decode op SIZE out of bounds, op #%d type=%d, offs=%d ($%04x), " + "bank=%d, size=%d ($%04x) vs. allocated %d ($%04x)\n", + i, op->type, op->offs, op->offs, op->bank, size, size, op->size, op->size); + return DMERR_INVALID_DATA; + } // Do we need to reallocate some more space? if (op->offs + size > len) @@ -706,8 +782,8 @@ case DT_COLOR_RAM: memcpy(img->color[op->bank], src, size); break; case DT_BITMAP: memcpy(img->bitmap[op->bank], src, size); break; case DT_SCREEN_RAM: memcpy(img->screen[op->bank], src, size); break; + case DT_CHAR_DATA: memcpy(img->charmem[op->bank], src, size); break; case DT_EXTRADATA: memcpy(img->extradata, src, size); break; - case DT_CHAR_DATA: memcpy(img->charmem, src, size); break; case DT_COLOR_REG: switch (op->size) @@ -751,9 +827,9 @@ case D64_CHCFG_LINEAR: { - size_t bank, offs; + int bank, offs; for (bank = 0; bank < C64_SCR_MAX_BANK; bank++) - for (offs = 0; offs < C64_SCR_SCREEN_SIZE; offs++) + for (offs = 0; offs < fmt->ch_height * fmt->ch_width; offs++) img->screen[bank][offs] = offs & 0xff; } break; @@ -831,7 +907,13 @@ goto error; // Check size - size = dmC64GetOpSize(op, fmt); + if (!dmC64GetOpSize(op, fmt, &size)) + { + dmError("Decode op SIZE out of bounds, op #%d type=%d, offs=%d ($%04x), " + "bank=%d, size=%d ($%04x) vs. allocated %d ($%04x)\n", + i, op->type, op->offs, op->offs, op->bank, size, size, op->size, op->size); + return DMERR_INVALID_DATA; + } // Do we need to reallocate some more space? if (2 + op->offs + size > allocated) @@ -858,8 +940,8 @@ case DT_COLOR_RAM: memcpy(dst, img->color[op->bank], size); break; case DT_BITMAP: memcpy(dst, img->bitmap[op->bank], size); break; case DT_SCREEN_RAM: memcpy(dst, img->screen[op->bank], size); break; + case DT_CHAR_DATA: memcpy(dst, img->charmem[op->bank], size); break; case DT_EXTRADATA: memcpy(dst, img->extradata, size); break; - case DT_CHAR_DATA: memcpy(dst, img->charmem, size); break; case DT_COLOR_REG: switch (op->size) @@ -938,37 +1020,39 @@ if (dst == NULL || src == NULL) return DMERR_NULLPTR; - if (dst->width < 8) - return DMERR_INVALID_ARGS; + if (dst->width < src->width || dst->height < src->height) + return DMERR_INVALID_DATA; - if (src->type & D64_FMT_CHAR) - for (yc = 0; yc < dst->height; yc++) + memset(dst->data, 0, dst->size); + + // Perform conversion + for (yc = 0; yc < src->height; yc++) { Uint8 *d = dp; const int y = yc / 8, yb = yc & 7; - const int scroffsy = y * C64_SCR_CH_WIDTH; + const int scroffsy = y * src->ch_width; int xc; - if ((src->type & D64_FMT_MC) == D64_FMT_HIRES) + if (src->type & D64_FMT_CHAR) { + // Charmode conversion + if ((src->type & D64_FMT_MC) == D64_FMT_HIRES) // Hi-res charmap - for (xc = 0; xc < dst->width; xc++) + for (xc = 0; xc < src->width; xc++) { const int x = xc / 8; const int scroffs = scroffsy + x; const int chr = src->screen[0][scroffs]; const int v = 7 - (xc & 7); - if ((src->charmem[chr][yb] >> v) & 1) + if ((src->charmem[0][chr * C64_CHR_SIZE + yb] >> v) & 1) *d++ = src->color[0][scroffs]; else *d++ = src->bgcolor; } - } - else - { + else // Multicolor variants - for (xc = 0; xc < dst->width / wdivisor; xc++) + for (xc = 0; xc < src->width / wdivisor; xc++) { const int x = xc / 4; const int scroffs = scroffsy + x; @@ -976,7 +1060,7 @@ const int v = 6 - ((xc * 2) & 6); Uint8 c; - switch ((src->charmem[chr][yb] >> v) & 3) + switch ((src->charmem[0][chr * C64_CHR_SIZE + yb] >> v) & 3) { case 0: c = src->bgcolor; break; case 1: c = src->d022; break; @@ -989,22 +1073,14 @@ *d++ = c; } } - dp += dst->pitch; - } - else - // Perform generic BITMAP conversion - for (yc = 0; yc < dst->height; yc++) - { - Uint8 *d = dp; - const int y = yc / 8, yb = yc & 7; - const int scroffsy = y * C64_SCR_CH_WIDTH; - const int bmoffsy = y * C64_SCR_WIDTH; - int xc; + else + { + // Perform generic BITMAP conversion + const int bmoffsy = y * src->width; - if ((src->type & D64_FMT_MC) == D64_FMT_HIRES) - { + if ((src->type & D64_FMT_MC) == D64_FMT_HIRES) // Hi-res bitmap - for (xc = 0; xc < dst->width; xc++) + for (xc = 0; xc < src->width; xc++) { const int x = xc / 8; const int scroffs = scroffsy + x; @@ -1016,11 +1092,9 @@ else *d++ = src->screen[0][scroffs] & 15; } - } - else - { - // Multicolor variants - for (xc = 0; xc < dst->width / wdivisor; xc++) + else + // Multicolor bitmap and variants + for (xc = 0; xc < src->width / wdivisor; xc++) { const int x = xc / 4; const int scroffs = scroffsy + x; @@ -1104,10 +1178,13 @@ } -int dmC64DecodeBMP(DMC64Image *img, const Uint8 *buf, const size_t len, +int dmC64DecodeBMP(DMC64Image **img, const Uint8 *buf, const size_t len, const size_t probeOffs, const size_t loadOffs, const DMC64ImageFormat **fmt, const DMC64ImageFormat *forced) { + if (img == NULL) + return DMERR_NULLPTR; + // Check for forced format if (forced != NULL) *fmt = forced; @@ -1115,18 +1192,26 @@ { // Nope, perform a generic probe if (probeOffs >= len) - return -200; + return DMERR_INVALID_DATA; if (dmC64ProbeBMP(buf + probeOffs, len - probeOffs, fmt) == DM_PROBE_SCORE_FALSE) - return -201; + return DMERR_INVALID_DATA; } if (loadOffs >= len) - return -203; + return DMERR_INVALID_ARGS; + + if (*fmt == NULL) + return DMERR_INVALID_DATA; + + // Allocate memory + if ((*img = dmC64ImageAlloc((*fmt)->width, (*fmt)->height, + (*fmt)->ch_width, (*fmt)->ch_height)) == NULL) + return DMERR_MALLOC; // Decode the bitmap to memory layout if ((*fmt)->decode != NULL) - return (*fmt)->decode(img, buf + loadOffs, len - loadOffs, *fmt); + return (*fmt)->decode(*img, buf + loadOffs, len - loadOffs, *fmt); else - return dmC64DecodeGenericBMP(img, buf + loadOffs, len - loadOffs, *fmt); + return dmC64DecodeGenericBMP(*img, buf + loadOffs, len - loadOffs, *fmt); }
--- a/tools/lib64gfx.h Wed Feb 25 19:32:55 2015 +0200 +++ b/tools/lib64gfx.h Wed Feb 25 19:37:59 2015 +0200 @@ -133,14 +133,17 @@ laceBank1, // Interlace video bank indices laceBank2; + int width, height; // Width and height in pixels + int ch_width, ch_height; // Width and height in charblocks + Uint8 - color[C64_SCR_MAX_BANK][C64_SCR_COLOR_SIZE], - bitmap[C64_SCR_MAX_BANK][C64_SCR_BITMAP_SIZE], - screen[C64_SCR_MAX_BANK][C64_SCR_SCREEN_SIZE], + *color[C64_SCR_MAX_BANK], + *bitmap[C64_SCR_MAX_BANK], + *screen[C64_SCR_MAX_BANK], + *charmem[C64_SCR_MAX_BANK], extradata[C64_SCR_EXTRADATA], d020, bgcolor, d022, d023, d024; - Uint8 charmem[C64_MAX_CHARS][C64_CHR_HEIGHT * C64_CHR_WIDTH]; DMC64Sprite sprites[C64_MAX_SPRITES]; } DMC64Image; @@ -206,6 +209,10 @@ extern const int ndmC64ImageFormats; +DMC64Image *dmC64ImageAlloc(int width, int height, int ch_width, int ch_height); +void dmC64ImageFree(DMC64Image *img); + + char * dmC64GetImageTypeString(char *buf, const size_t len, const int type); int dmC64ConvertCSDataToImage(DMImage *img, int xoffs, int yoffs, const Uint8 *inBuf, int width, int height, BOOL multicolor, int *colors); @@ -215,7 +222,7 @@ int dmC64ConvertBMP2Image(DMImage **pdst, const DMC64Image *src, const DMC64ImageFormat *fmt, const BOOL doubleMC); int dmC64ProbeBMP(const Uint8 *buf, const size_t len, const DMC64ImageFormat **fmt); -int dmC64DecodeBMP(DMC64Image *img, const Uint8 *buf, const size_t len, const size_t probeOffs, const size_t loadOffs, const DMC64ImageFormat **fmt, const DMC64ImageFormat *forced); +int dmC64DecodeBMP(DMC64Image **img, const Uint8 *buf, const size_t len, const size_t probeOffs, const size_t loadOffs, const DMC64ImageFormat **fmt, const DMC64ImageFormat *forced); #ifdef __cplusplus
--- a/tools/view64.c Wed Feb 25 19:32:55 2015 +0200 +++ b/tools/view64.c Wed Feb 25 19:37:59 2015 +0200 @@ -157,7 +157,7 @@ DMImage bmap; BOOL initSDL = FALSE, exitFlag, needRedraw; const DMC64ImageFormat *fmt = NULL, *forced; - DMC64Image image; + DMC64Image *cimage = NULL; char *windowTitle; Uint8 *dataBuf = NULL; size_t dataSize; @@ -194,7 +194,7 @@ else forced = NULL; - ret = dmC64DecodeBMP(&image, dataBuf, dataSize, 0, 2, &fmt, forced); + ret = dmC64DecodeBMP(&cimage, dataBuf, dataSize, 0, 2, &fmt, forced); if (forced == NULL && fmt != NULL) { dmMsg(0,"Probed %s format image, type %d, %s\n", @@ -231,6 +231,7 @@ SDL_SetColors(screen, (SDL_Color *)dmC64Palette, 0, C64_NCOLORS); // Convert bitmap (this is a bit ugly and lazy here) + bmap.size = surf->pitch * surf->h; bmap.data = surf->pixels; bmap.pitch = surf->pitch; bmap.width = surf->w; @@ -238,9 +239,9 @@ bmap.constpal = TRUE; if (fmt->convertFrom != NULL) - ret = fmt->convertFrom(&bmap, &image, TRUE); + ret = fmt->convertFrom(&bmap, cimage, TRUE); else - ret = dmC64ConvertGenericBMP2Image(&bmap, &image, TRUE); + ret = dmC64ConvertGenericBMP2Image(&bmap, cimage, TRUE); // Set window title and caption