Mercurial > hg > dmlib
view tools/view64.c @ 1401:aaed8fa9a11f
Fix jssASCIItoStr() bounds check.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 30 Oct 2017 18:01:25 +0200 |
parents | 009534f27de5 |
children | 89725addaeaf |
line wrap: on
line source
/* * view64 - Display some C64 etc graphics formats via libSDL * Programmed and designed by Matti 'ccr' Hamalainen * (C) Copyright 2012 Tecnic Software productions (TNSP) * * Please read file 'COPYING' for information on license and distribution. */ #include "dmlib.h" #include "dmargs.h" #include "dmfile.h" #include "lib64gfx.h" #include <SDL.h> char * optFilename = NULL; int optVFlags = SDL_SWSURFACE | SDL_HWPALETTE; int optScrWidth, optScrHeight; int optForcedFormat = -1; BOOL optProbeOnly = FALSE; static const DMOptArg optList[] = { { 0, '?', "help", "Show this help", OPT_NONE }, { 1, 'v', "verbose", "Be more verbose", OPT_NONE }, { 2, 0, "fs", "Fullscreen", OPT_NONE }, { 3, 'S', "scale", "Scale image by factor (1-10)", OPT_ARGREQ }, { 4, 'f', "format", "Force input format (see list below)", OPT_ARGREQ }, { 5, 'p', "probe", "Probe only (no display)", OPT_NONE }, }; const int optListN = sizeof(optList) / sizeof(optList[0]); void dmSetScaleFactor(float factor) { optScrWidth = (int) ((float) C64_SCR_WIDTH * factor * C64_SCR_PAR_XY); optScrHeight = (int) ((float) C64_SCR_HEIGHT * factor); } void argShowHelp() { dmPrintBanner(stdout, dmProgName, "[options] <input image file>"); dmArgsPrintHelp(stdout, optList, optListN, 0); printf("\nAvailable bitmap formats:\n"); for (int i = 0; i < ndmC64ImageFormats; i++) { const DMC64ImageFormat *fmt = &dmC64ImageFormats[i]; char buf[64]; printf("%3d | %-5s | %-15s | %s\n", i, fmt->fext, dmC64GetImageTypeString(buf, sizeof(buf), fmt->type), fmt->name); } } BOOL argHandleOpt(const int optN, char *optArg, char *currArg) { switch (optN) { case 0: argShowHelp(); exit(0); break; case 1: dmVerbosity++; break; case 2: optVFlags |= SDL_FULLSCREEN; break; case 3: { float factor; if (sscanf(optArg, "%f", &factor) == 1) { if (factor < 1 || factor >= 10) { dmErrorMsg("Invalid scale factor %1.0f, see help for valid values.\n", factor); return FALSE; } dmSetScaleFactor(factor); } else { dmErrorMsg("Invalid scale factor '%s'.\n", optArg); return FALSE; } } break; case 4: { int i; if (sscanf(optArg, "%d", &i) == 1) { if (i < 0 || i >= ndmC64ImageFormats) { dmErrorMsg("Invalid image format index %d, see help for valid values.\n", i); return FALSE; } optForcedFormat = i; } else { dmErrorMsg("Invalid image format argument '%s'.\n", optArg); return FALSE; } } break; case 5: if (dmVerbosity < 1) dmVerbosity = 1; optProbeOnly = TRUE; break; default: dmErrorMsg("Unknown option '%s'.\n", currArg); return FALSE; } return TRUE; } BOOL argHandleFile(char *filename) { if (optFilename == NULL) { optFilename = dm_strdup(filename); return TRUE; } else { dmErrorMsg("Too many filenames specified ('%s')\n", filename); return FALSE; } } BOOL dmInitializeVideo(SDL_Surface **screen) { *screen = SDL_SetVideoMode(optScrWidth, optScrHeight, 8, optVFlags | SDL_RESIZABLE); if (*screen == NULL) { dmErrorMsg("Can't SDL_SetVideoMode(): %s\n", SDL_GetError()); return FALSE; } return TRUE; } void dmDumpC64Image(const size_t size, const DMC64Image *img, const DMC64ImageFormat *fmt) { char typeStr[64]; snprintf(typeStr, sizeof(typeStr), "%s%s%s%s", ((img->type & D64_FMT_MC) ? "MultiColor" : "Hires"), ((img->type & D64_FMT_ILACE) ? " Interlaced" : ""), ((img->type & D64_FMT_FLI) ? " FLI" : ""), ((img->type & D64_FMT_CHAR) ? " CHAR" : "") ); dmPrint(1, "Format : %s [%s]\n" "Data size : %" DM_PRIu_SIZE_T "\n" "Type : %s\n" "Banks : %d\n", fmt->name, fmt->fext, size, typeStr, img->nbanks); if (img->type & D64_FMT_ILACE) { char *tmps; switch(img->laceType) { case D64_ILACE_COLOR: tmps = "color"; break; case D64_ILACE_RES: tmps = "resolution"; break; default: tmps = "ERROR"; break; } dmPrint(1, "Interlace type : %s\n", tmps); } dmPrint(1, "Width x Height : %d x %d\n" "CHwidth x CHheight : %d x %d\n", img->width, img->height, img->ch_width, img->ch_height); } int main(int argc, char *argv[]) { SDL_Surface *screen = NULL, *surf = NULL; DMImage bmap; BOOL initSDL = FALSE, exitFlag, needRedraw; const DMC64ImageFormat *fmt = NULL, *forced; DMC64Image *cimage = NULL; char *windowTitle; Uint8 *dataBuf = NULL; size_t dataSize; int ret; dmSetScaleFactor(2.0); dmInitProg("view64", "Display some C64 bitmap graphics formats", "0.2", NULL, NULL); /* Parse arguments */ if (!dmArgsProcess(argc, argv, optList, optListN, argHandleOpt, argHandleFile, OPTH_BAILOUT)) exit(1); if (optFilename == NULL) { dmErrorMsg("No input file specified, perhaps you need some --help\n"); goto error; } dmPrint(1, "\n%s\n", optFilename); if ((ret = dmReadDataFile(NULL, optFilename, &dataBuf, &dataSize)) != DMERR_OK) goto error; // Probe for format if (optForcedFormat >= 0) { forced = &dmC64ImageFormats[optForcedFormat]; dmMsg(0, "Forced %s format image, type %d, %s\n", forced->name, forced->type, forced->fext); } else forced = NULL; ret = dmC64DecodeBMP(&cimage, dataBuf, dataSize, 0, 2, &fmt, forced); if (ret < 0) { dmErrorMsg("Failed to decode bitmap data %d: %s\n", ret, dmErrorStr(ret)); goto error; } if (fmt == NULL) { dmErrorMsg("Probing could not find any matching image format. Perhaps try forcing a format via -f.\n"); goto error; } dmDumpC64Image(dataSize, cimage, fmt); if (optProbeOnly) goto error; // Initialize libSDL if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) { dmErrorMsg("Could not initialize SDL: %s\n", SDL_GetError()); goto error; } initSDL = TRUE; // Open window/set video mode screen = SDL_SetVideoMode(optScrWidth, optScrHeight, 8, optVFlags | SDL_RESIZABLE); if (screen == NULL) { dmErrorMsg("Can't SDL_SetVideoMode(): %s\n", SDL_GetError()); goto error; } // Create surface (we are lazy and ugly) surf = SDL_CreateRGBSurface(SDL_SWSURFACE, cimage->width, cimage->height, 8, 0, 0, 0, 0); SDL_SetColors(surf, (SDL_Color *)dmC64Palette, 0, C64_NCOLORS); 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; bmap.height = surf->h; bmap.constpal = TRUE; if (fmt->convertFrom != NULL) ret = fmt->convertFrom(&bmap, cimage, fmt); else ret = dmC64ConvertGenericBMP2Image(&bmap, cimage, fmt); // Set window title and caption windowTitle = dm_strdup_printf("%s - %s (%d x %d)", dmProgName, optFilename, cimage->width, cimage->height); SDL_WM_SetCaption(windowTitle, dmProgName); dmFree(windowTitle); // Start main loop needRedraw = TRUE; exitFlag = FALSE; while (!exitFlag) { SDL_Event event; while (SDL_PollEvent(&event)) switch (event.type) { case SDL_KEYDOWN: switch (event.key.keysym.sym) { case SDLK_ESCAPE: exitFlag = TRUE; break; default: break; } needRedraw = TRUE; break; case SDL_VIDEORESIZE: optScrWidth = event.resize.w; optScrHeight = event.resize.h; if (!dmInitializeVideo(&screen)) goto error; needRedraw = TRUE; break; case SDL_VIDEOEXPOSE: needRedraw = TRUE; break; case SDL_QUIT: exit(0); } if (needRedraw) { float aspect = (float) bmap.height / (float) bmap.width; int sheight = optScrHeight / aspect; int ypos = (optScrHeight - sheight) / 2; if (SDL_MUSTLOCK(screen) != 0 && SDL_LockSurface(screen) != 0) { dmErrorMsg("Can't lock surface.\n"); goto error; } dmScaledBlitSurface8to8(surf, 0, ypos, optScrWidth, sheight, screen); SDL_SetColors(screen, (SDL_Color *)dmC64Palette, 0, C64_NCOLORS); if (SDL_MUSTLOCK(screen) != 0) SDL_UnlockSurface(screen); SDL_Flip(screen); needRedraw = FALSE; } SDL_Delay(100); } error: dmC64ImageFree(cimage); if (screen) SDL_FreeSurface(screen); if (initSDL) SDL_Quit(); return 0; }