Mercurial > hg > dmlib
diff tools/64vw.c @ 1435:e6fbefa96899
Rename view64 to 64vw.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 12 Dec 2017 01:59:29 +0200 |
parents | tools/view64.c@4c7b456d7f0b |
children | 0d5295a5af57 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/64vw.c Tue Dec 12 01:59:29 2017 +0200 @@ -0,0 +1,489 @@ +/* + * 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> + + +int optVFlags = SDL_SWSURFACE | SDL_HWPALETTE; +int optScrWidth, optScrHeight; +int optForcedFormat = -1; +BOOL optProbeOnly = FALSE; +size_t noptFilenames1 = 0, noptFilenames2 = 0; +char **optFilenames = NULL; + + +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 argHandleFile1(char *filename) +{ + (void) filename; + + noptFilenames1++; + return TRUE; +} + + +BOOL argHandleFile2(char *filename) +{ + if (noptFilenames2 < noptFilenames1) + { + optFilenames[noptFilenames2++] = filename; + return TRUE; + } + else + 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 char *filename, 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, + "\n%s\n" + "Format : %s [%s]\n" + "Type : %s\n" + "Banks : %d\n", + filename, + fmt->name, fmt->fext, + 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 dmReadC64Image(const char *filename, const DMC64ImageFormat *forced, const DMC64ImageFormat **fmt, DMC64Image **cimage) +{ + Uint8 *dataBuf = NULL; + size_t dataSize; + int ret; + + if ((ret = dmReadDataFile(NULL, filename, &dataBuf, &dataSize)) != DMERR_OK) + goto exit; + + ret = dmC64DecodeBMP(cimage, dataBuf, dataSize, 0, 2, fmt, forced); + +exit: + dmFree(dataBuf); + return ret; +} + + +int dmDecodeC64Image(const DMC64Image *cimage, const DMC64ImageFormat *fmt, SDL_Surface *surf) +{ + DMImage bmap; + int ret; + + bmap.size = surf->pitch * surf->h; + bmap.data = surf->pixels; + bmap.pitch = surf->pitch; + bmap.width = surf->w; + bmap.height = surf->h; + + if (fmt->convertFrom != NULL) + ret = fmt->convertFrom(&bmap, cimage, fmt); + else + ret = dmC64ConvertGenericBMP2Image(&bmap, cimage, fmt); + + return ret; +} + + +int main(int argc, char *argv[]) +{ + SDL_Surface *screen = NULL, *surf = NULL; + BOOL initSDL = FALSE, exitFlag, needRedraw; + const DMC64ImageFormat *forced; + size_t currIndex, prevIndex; + int ret; + + dmSetScaleFactor(2.0); + + dmInitProg("view64", "Display some C64 bitmap graphics formats", "0.2", NULL, NULL); + + // Parse arguments, round #1 + if (!dmArgsProcess(argc, argv, optList, optListN, + argHandleOpt, argHandleFile1, OPTH_BAILOUT)) + exit(1); + + if (noptFilenames1 == 0) + { + dmErrorMsg("No input file(s) specified, perhaps you need some --help\n"); + goto exit; + } + + // Allocate space for filename pointers + if ((optFilenames = dmCalloc(noptFilenames1, sizeof(char *))) == NULL) + { + dmErrorMsg("Could not allocate memory for input file list.\n"); + goto exit; + } + + // Assign the filename pointers + if (!dmArgsProcess(argc, argv, optList, optListN, + NULL, argHandleFile2, OPTH_BAILOUT | OPTH_ONLY_OTHER)) + goto exit; + + // Check for forced input 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; + + // If we are simply probing, no need to initialize SDL etc + if (optProbeOnly) + { + for (size_t n = 0; n < noptFilenames2; n++) + { + char *filename = optFilenames[n]; + const DMC64ImageFormat *fmt = NULL; + DMC64Image *cimage = NULL; + + if ((ret = dmReadC64Image(filename, forced, &fmt, &cimage)) != DMERR_OK) + { + dmErrorMsg("Could not read image file '%s', %d: %s\n", + filename, ret, dmErrorStr(ret)); + } + else + { + dmDumpC64Image(filename, cimage, fmt); + } + + dmC64ImageFree(cimage); + } + goto exit; + } + + // Initialize libSDL + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) + { + dmErrorMsg("Could not initialize SDL: %s\n", SDL_GetError()); + goto exit; + } + 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 exit; + } + + // Start main loop + currIndex = 0; + prevIndex = 1; + 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: + case SDLK_q: + exitFlag = TRUE; + break; + + case SDLK_LEFT: + if (currIndex > 0) + currIndex--; + break; + + case SDLK_RIGHT: + if (currIndex < noptFilenames2 - 1) + currIndex++; + break; + + default: + break; + } + + needRedraw = TRUE; + break; + + case SDL_VIDEORESIZE: + optScrWidth = event.resize.w; + optScrHeight = event.resize.h; + if (!dmInitializeVideo(&screen)) + goto exit; + + needRedraw = TRUE; + break; + + case SDL_VIDEOEXPOSE: + needRedraw = TRUE; + break; + + case SDL_QUIT: + goto exit; + } + + if (currIndex != prevIndex) + { + char *filename = optFilenames[currIndex]; + const DMC64ImageFormat *fmt = NULL; + DMC64Image *cimage = NULL; + char *title = NULL; + + if (surf != NULL) + { + SDL_FreeSurface(surf); + surf = NULL; + } + + if ((ret = dmReadC64Image(filename, forced, &fmt, &cimage)) != DMERR_OK) + { + dmErrorMsg("Failed to decode bitmap data %d: %s\n", ret, dmErrorStr(ret)); + goto fail; + } + + if (fmt == NULL || cimage == NULL) + { + dmErrorMsg("Probing could not find any matching image format. Perhaps try forcing a format via -f.\n"); + goto fail; + } + + // Create surface (we are lazy and ugly) + if ((surf = SDL_CreateRGBSurface(SDL_SWSURFACE, cimage->width, cimage->height, 8, 0, 0, 0, 0)) == NULL) + { + dmErrorMsg("Could not allocate surface.\n"); + goto exit; + } + + if (dmDecodeC64Image(cimage, fmt, surf) == DMERR_OK) + { + title = dm_strdup_printf("%s - %s (%d x %d) [%d / %d]", + dmProgName, filename, + cimage->width, cimage->height, + currIndex + 1, noptFilenames2); + + dmDumpC64Image(filename, cimage, fmt); + } + +fail: + if (surf == NULL && (surf = SDL_CreateRGBSurface(SDL_SWSURFACE, 320, 200, 8, 0, 0, 0, 0)) == NULL) + { + dmErrorMsg("Could not allocate surface.\n"); + goto exit; + } + + if (title == NULL) + { + title = dm_strdup_printf("%s [%d / %d]", + dmProgName, + currIndex + 1, noptFilenames2); + } + + SDL_WM_SetCaption(title, dmProgName); + dmFree(title); + + needRedraw = TRUE; + prevIndex = currIndex; + } + + if (needRedraw) + { + float aspect = (float) surf->h / (float) surf->w; + 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 exit; + } + + dmScaledBlitSurface8to8(surf, 0, ypos, optScrWidth, sheight, screen); + SDL_SetColors(screen, (SDL_Color *)dmDefaultC64Palette, 0, C64_NCOLORS); + + if (SDL_MUSTLOCK(screen) != 0) + SDL_UnlockSurface(screen); + + SDL_Flip(screen); + needRedraw = FALSE; + } + + SDL_Delay(50); + } + +exit: + // Cleanup + dmFree(optFilenames); + + if (screen != NULL) + SDL_FreeSurface(screen); + + if (surf != NULL) + SDL_FreeSurface(surf); + + if (initSDL) + SDL_Quit(); + + return 0; +}