view view64.c @ 510:43ea59887c69

Start work on making C64 formats encoding possible by changing DMDecodeOps to DMEncDecOps and adding fields and op enums for custom encode functions, renaming, etc. Split generic op sanity checking into a separate function in preparation for its use in generic encoding function.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 19 Nov 2012 15:06:01 +0200
parents e8e244036ee4
children 6f141f760c54
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;


static 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 },
};

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()
{
    int i;

    dmPrintBanner(stdout, dmProgName, "[options] <input image file>");
    dmArgsPrintHelp(stdout, optList, optListN);

    printf("\nAvailable bitmap formats:\n");
    for (i = 0; i < ndmC64ImageFormats; i++)
    {
        DMC64ImageFormat *fmt = &dmC64ImageFormats[i];
        printf("%3d | %-5s | %-15s | %s\n",
            i, fmt->extension,
            dmC64ImageTypeNames[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)
                    {
                        dmError("Invalid scale factor %1.0f, see help for valid values.\n", factor);
                        return FALSE;
                    }

                    dmSetScaleFactor(factor);
                }
                else
                {
                    dmError("Invalid scale factor '%s'.\n", optArg);
                    return FALSE;
                }
            }
            break;

        case 4:
            {
                int i;
                if (sscanf(optArg, "%d", &i) == 1)
                {
                    if (i < 0 || i >= ndmC64ImageFormats)
                    {
                        dmError("Invalid image format index %d, see help for valid values.\n", i);
                        return FALSE;
                    }
                    optForcedFormat = i;
                }
                else
                {
                    dmError("Invalid image format argument '%s'.\n", optArg);
                    return FALSE;
                }
            }
            break;
        
        default:
            dmError("Unknown option '%s'.\n", currArg);
            return FALSE;
    }
    
    return TRUE;
}


BOOL argHandleFile(char *filename)
{
    if (optFilename == NULL)
    {
        optFilename = dm_strdup(filename);
        return TRUE;
    }
    else
    {
        dmError("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)
    {
        dmError("Can't SDL_SetVideoMode(): %s\n", SDL_GetError());
        return FALSE;
    }
    return TRUE;
}


int main(int argc, char *argv[])
{
    SDL_Surface *screen = NULL, *surf = NULL;
    DMImage bmap;
    BOOL initSDL = FALSE, exitFlag, needRedraw;
    DMC64ImageFormat *fmt, *forced;
    DMC64Image image;
    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, FALSE))
        exit(1);


    if (optFilename == NULL)
    {
        dmError("No input file specified, perhaps you need some --help\n");
        goto error;
    }
        
    if ((ret = dmReadDataFile(NULL, optFilename, &dataBuf, &dataSize)) != DMERR_OK)
        goto error;

    dmMsg(1, "Read %d bytes of input.\n", dataSize);

    // Probe for format
    if (optForcedFormat >= 0)
    {
        forced = &dmC64ImageFormats[optForcedFormat];
        dmMsg(0,"Forced %s format image, type %d, %s\n", forced->name, forced->type, forced->extension);
    }
    else
        forced = NULL;

    ret = dmC64DecodeBMP(&image, dataBuf, dataSize, 0, 2, &fmt, forced);
    if (forced == NULL && fmt != NULL)
    {
        dmMsg(0,"Probed %s format image, type %d, %s\n",
            fmt->name, fmt->type, fmt->extension);
    }

    if (ret < 0)
    {
        dmError("Probing could not find any matching image format (%d). Perhaps try forcing a format via -f\n", ret);
        return -1;
    }


    // Initialize libSDL
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0)
    {
        dmError("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)
    {
        dmError("Can't SDL_SetVideoMode(): %s\n", SDL_GetError());
        goto error;
    }

    // Create surface (we are lazy and ugly)
    surf = SDL_CreateRGBSurface(SDL_SWSURFACE, C64_SCR_WIDTH, C64_SCR_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.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, &image);
    else
        ret = dmC64ConvertGenericBMP2Image(&bmap, &image);


    // Set window title and caption
    windowTitle = dm_strdup_printf("%s - %s", dmProgName, optFilename);
    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)
        {
            if (SDL_MUSTLOCK(screen) != 0 && SDL_LockSurface(screen) != 0)
            {
                dmError("Can't lock surface.\n");
                goto error;
            }
            
            dmScaledBlitSurface8to8(surf, 0, 0, screen->w, screen->h, 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:
    if (screen)
        SDL_FreeSurface(screen);

    if (initSDL)
        SDL_Quit();

    return 0;
}