view vview.c @ 96:6bf5220fa47e

Urgh .. use memset to silence some bogus GCC warnings about using potentially uninitialized values, while that will not actually be possible. In any case, it is annoying.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 02 Oct 2012 18:52:28 +0300
parents daeb5d4f6bad
children
line wrap: on
line source

#include "dmlib.h"
#include "dmargs.h"
#include "dmtext.h"

#define DM_COLORS (256)

char *optFilename = NULL, *optFontFile = "font.ttf";
int optVFlags = SDL_SWSURFACE | SDL_HWPALETTE;
int optScrWidth = 640, optScrHeight = 480, optFontSize = 20, optScrDepth = 32;
BOOL optShowSurfaceInfo = FALSE;

DMOptArg optList[] = {
    { 0, '?', "help",       "Show this help", OPT_NONE },
    { 2, 'v', "verbose",    "Be more verbose", OPT_NONE },
    { 3, 'f', "full",       "Fullscreen", OPT_NONE },
    { 4, 'h', "hw",         "Use SDL hardware surface", OPT_NONE },
    { 5, 's', "size",       "Initial window size/resolution -s 640x480", OPT_ARGREQ },
    { 6, 'd', "depth",      "Color depth of mode/window in bits (8/15/16/32)", OPT_ARGREQ },
    { 7, 'i', "info",       "Print out extra information on used SDL surfaces", OPT_NONE }
};

const int optListN = sizeof(optList) / sizeof(optList[0]);


void argShowHelp()
{
    dmPrintBanner(stdout, dmProgName, "[options] <datafile>");
    dmArgsPrintHelp(stdout, optList, optListN);
}


BOOL argHandleOpt(const int optN, char *optArg, char *currArg)
{
    switch (optN) {
    case 0:
        argShowHelp();
        exit(0);
        break;

    case 2:
        dmVerbosity++;
        break;
    
    case 3:
        optVFlags |= SDL_FULLSCREEN;
        break;

    case 6:
        if (optArg)
            optScrDepth = atoi(optArg);
        break;
    
    case 7:
        optShowSurfaceInfo = TRUE;
        break;

    case 5:
        {
            int w, h;
            if (sscanf(optArg, "%dx%d", &w, &h) == 2)
            {
                if (w < 320 || h < 200 || w > 3200 || h > 3200)
                {
                    dmError("Invalid width or height: %d x %d\n", w, h);
                    return FALSE;
                }
                optScrWidth = w;
                optScrHeight = h;
            }
            else 
            {
                dmError("Invalid size 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;
    }
}

void DM_MakePalette(SDL_Color *pal)
{
    int n;

    for (n = 0; n < 64; n++)
    {
        pal[n].r = n * 2;
        pal[n].g = 0;
        pal[n].b = 0;
    }

    for (n = 64; n < 128; n++)
    {
        pal[n].r = n * 2;
        pal[n].g = (n - 64) * 4;
        pal[n].b = (n - 64) * 4;
    }

    for (n = 128; n < 192; n++)
    {
        pal[n].r = (255 - n) * 4;
        pal[n].g = (255 - n) * 2;
        pal[n].b = (255 - n) * 2;
    }

    for (n = 192; n < 256; n++)
    {
        pal[n].r = 0;
        pal[n].g = (255 - n) * 2;
        pal[n].b = (255 - n) * 2;
    }
}


void DM_CreatePaletteFrom(SDL_Color *pal, Uint8 *buf)
{
    int n, offs;
    for (offs = n = 0; n < DM_COLORS; n++)
    {
        pal[n].r = buf[offs++];
        pal[n].g = buf[offs++];
        pal[n].b = buf[offs++];
    }
}

void printSurface(FILE *f, SDL_Surface *s, const char *name)
{
    if (!optShowSurfaceInfo || s == NULL) return;
    
    fprintf(f, "\nSDL_Surface[%p]: %s:\n"
    "  flags   : 0x%08x\n"
    "  format  : %p\n", s, name, s->flags, s->format);
    if (s->format != NULL)
    {
        SDL_PixelFormat *pf = s->format;
        fprintf(f,
        "    palette       : %p\n"
        "    BitsPerPixel  : %d\n"
        "    BytesPerPixel : %d\n"
        "    colorkey      : %d (%08x)\n"
        "    alpha         : %d\n",
        pf->palette,
        pf->BitsPerPixel,
        pf->BytesPerPixel,
        pf->colorkey, pf->colorkey,
        pf->alpha);

        fprintf(f,
        "    R/G/B/A loss  : %d / %d / %d / %d\n"
        "    R/G/B/A shift : %d / %d / %d / %d\n"
        "    R/G/B/A mask  : %08x / %08x / %08x / %08x\n",
        pf->Rloss  , pf->Gloss  , pf->Bloss  , pf->Aloss,
        pf->Rshift , pf->Gshift , pf->Bshift , pf->Ashift,
        pf->Rmask  , pf->Gmask  , pf->Bmask  , pf->Amask
        );
    }
    fprintf(f,
    "  W x H  : %d x %d\n"
    "  pitch  : %d bytes\n"
    "  pixels : %p\n\n",
    s->w, s->h,
    s->pitch,
    s->pixels);
}

BOOL DM_InitializeVideo(SDL_Surface **screen)
{
    *screen = SDL_SetVideoMode(optScrWidth, optScrHeight, optScrDepth, optVFlags | SDL_RESIZABLE);
    if (*screen == NULL)
    {
        dmError("Can't SDL_SetVideoMode(): %s\n", SDL_GetError());
        return FALSE;
    }
    printSurface(stdout, *screen, "screen");
    return TRUE;
}

void DM_UnRLE(Uint8 *dst, Uint8 **udata, const Uint8 *dp, const int rleMarker, const Uint8 *de)
{
    Uint8 *data = *udata;

    while (data < dp && dst < de)
    {
        int c = *data++;
        if ((c & rleMarker) == rleMarker)
        {
            int cnt = c & (0xff ^ rleMarker);
            c = *data++;
            while (cnt-- && dst < de)
                *dst++ = c;
        }
        else
            *dst++ = c;
    }
    
    *udata = data;
}

void DM_Redraw(SDL_Surface *screen, Uint8 *data, int skip, int useRLE, int rleMarker)
{
    Uint8 *pix = screen->pixels;
    
    if (useRLE)
    {
        const int tmpmax = screen->w * 64;
        Uint8 *tmp = dmMalloc(tmpmax);
        const Uint8 *dp = data + (screen->w * screen->h);

        if (skip > tmpmax)
            skip = tmpmax;

        if (useRLE == 1)
        {
            int yc;
            for (yc = 0; yc < screen->h; yc++)
            {
                memset(tmp, 0xff, tmpmax);
                DM_UnRLE(tmp, &data, dp, rleMarker, tmp + tmpmax);
                memcpy(pix, tmp, screen->w);
                pix += screen->pitch;
            }
        }
        else
        if (useRLE == 2)
        {
            int yc;
            for (yc = 0; yc < screen->h; yc++)
            {
                memset(tmp, 0xff, tmpmax);
                DM_UnRLE(tmp, &data, dp, rleMarker, tmp + skip);
                memcpy(pix, tmp, screen->w);
                pix += screen->pitch;
            }
        }
        else
        {
            printf("useRLE=%d\n", useRLE);
        }

        dmFree(tmp);
    }
    else
    {
        int yc;
        for (yc = 0; yc < screen->h; yc++)
        {
            int xc;
            for (xc = 0; xc < screen->w; xc++)
                pix[xc] = *data++;
            pix += screen->pitch;
        }
    }
}

void DM_Random(SDL_Surface *screen, int q)
{
    Uint8 *pix = screen->pixels;
    int xc, yc;
    
    for (yc = 0; yc < screen->h; yc++)
    {
        Uint8 *dp = pix;

        for (xc = 0; xc < screen->w; xc++)
            *dp++ = (xc * q + yc * q);

        pix += screen->pitch;
    }
}

void adjustValue(int *val, int min, int max, int delta)
{
    *val += delta;
    if (*val < min) *val = min;
    else if (*val > max) *val = max;
}

int main(int argc, char *argv[])
{
    SDL_Color pal[256];
    SDL_Surface *screen = NULL, *bmap = NULL;
    TTF_Font *font = NULL;
    SDL_Color fontcol={255,255,255,0};
    SDL_Event event;
    Uint8 *scrData = NULL;
    size_t scrSize = 0;
    int scrWidth = 128, scrHeight = 128, scrPalOffs = 0, scrOffs = 0, scrSkip = 0;
    BOOL initSDL = FALSE, initTTF = FALSE,
         exitFlag, needRedraw, palChanged = FALSE, showTest = FALSE, useRLE = FALSE,
         showHex = FALSE, scrPalette = FALSE, scrChanged;

    // Initialize
    dmInitProg("vtest", "vtester", "0.1", NULL, NULL);
    
    // Parse arguments
    if (!dmArgsProcess(argc, argv, optList, optListN,
        argHandleOpt, argHandleFile, FALSE))
        exit(1);


    if (optFilename == NULL)
    {
        dmError("No input file specified.\n");
        goto error_exit;
    }
    else
    {
        FILE *f = fopen(optFilename, "rb");
        if (f == NULL)
        {
            dmError("Could not open input file '%s'\n");
            goto error_exit;
        }
        fseek(f, 0L, SEEK_END);
        scrSize = ftell(f);
        fseek(f, 0L, SEEK_SET);
        
        if ((scrData = malloc(scrSize)) == NULL)
        {
            fclose(f);
            dmError("Error allocating memory for data, %d bytes.\n", scrSize);
            goto error_exit;
        }
        
        fread(scrData, 1, scrSize, f);
        fclose(f);
    }


    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0)
    {
        dmError("Could not initialize SDL: %s\n", SDL_GetError());
        goto error_exit;
    }
    initSDL = TRUE;

    if (TTF_Init() < 0)
    {
        dmError("Could not initialize FreeType/TTF: %s\n", SDL_GetError());
        goto error_exit;
    }
    initTTF = TRUE;

    font = TTF_OpenFont(optFontFile, optFontSize);
    if (font == NULL)
    {
        dmError("Could not load TTF font '%s' (%d): %s\n",
            optFontFile, optFontSize, SDL_GetError());
        goto error_exit;
    }
    TTF_SetFontStyle(font, TTF_STYLE_NORMAL);
    
    if (!DM_InitializeVideo(&screen))
        goto error_exit;

    SDL_WM_SetCaption("Halleluja", "DMT");

    exitFlag = FALSE;
    scrChanged = palChanged = TRUE;

    while (!exitFlag)
    {
        while (SDL_PollEvent(&event))
        switch (event.type)
        {
            case SDL_KEYDOWN:
                {
                int amount = 10;
                
                if ((event.key.keysym.mod & KMOD_CTRL))
                    amount = 50;

                if ((event.key.keysym.mod & KMOD_SHIFT))
                    amount = 1;
                
                switch (event.key.keysym.sym)
                {
                    case SDLK_ESCAPE: exitFlag = TRUE; break;
                    case SDLK_LEFT:  adjustValue(&scrWidth,  0, 1024, -amount); scrChanged = TRUE; break;
                    case SDLK_RIGHT: adjustValue(&scrWidth,  0, 1024, amount); scrChanged = TRUE; break;
                    case SDLK_UP:    adjustValue(&scrHeight, 0, 1024, -amount); scrChanged = TRUE; break;
                    case SDLK_DOWN:  adjustValue(&scrHeight, 0, 1024, amount); scrChanged = TRUE; break;

                    case SDLK_F1:
                        scrPalette = !scrPalette;
                        palChanged = TRUE;
                        break;

                    case SDLK_F2:
                        showTest = !showTest;
                        break;
                    
                    case SDLK_F3: adjustValue(&scrPalOffs, 0, scrSize - 256 * 3, -amount); palChanged = TRUE; break;
                    case SDLK_F4: adjustValue(&scrPalOffs, 0, scrSize - 256 * 3, amount); palChanged = TRUE; break;

                    case SDLK_F5: adjustValue(&scrOffs, 0, scrSize, -amount); break;
                    case SDLK_F6: adjustValue(&scrOffs, 0, scrSize, amount); break;

                    case SDLK_F7: adjustValue(&scrSkip, 0, scrSize, -amount); break;
                    case SDLK_F8: adjustValue(&scrSkip, 0, scrSize, amount); break;

                    case SDLK_F9:
                        showHex = !showHex;
                        break;
                    
                    case SDLK_r:
                        useRLE = (useRLE + 1) % 3;
                        break;
                    
                    default:
                        break;
                }
                }

                needRedraw = TRUE;
                break;
            
            case SDL_VIDEORESIZE:
                optScrWidth = event.resize.w;
                optScrHeight = event.resize.h;

                if (!DM_InitializeVideo(&screen))
                    goto error_exit;

                needRedraw = TRUE;
                break;
            
            case SDL_VIDEOEXPOSE:
                needRedraw = TRUE;
                break;

            case SDL_QUIT:
                exit(0);
        }
        
        if (scrChanged)
        {
            SDL_FreeSurface(bmap);
            bmap = SDL_CreateRGBSurface(SDL_SWSURFACE, scrWidth, scrHeight, 8, 0, 0, 0, 0);
            printSurface(stdout, bmap, "bmap");
            needRedraw = TRUE;
            scrChanged = FALSE;
            palChanged = TRUE;
        }

        if (palChanged)
        {
            if (scrPalette)
                DM_CreatePaletteFrom(pal, scrData + scrPalOffs);
            else
                DM_MakePalette(pal);

            SDL_SetColors(bmap, pal, 0, DM_COLORS);
            palChanged = FALSE;
        }

        if (needRedraw)
        {
            if (SDL_MUSTLOCK(screen) != 0 && SDL_LockSurface(screen) != 0)
            {
                dmError("Can't lock surface.\n");
                goto error_exit;
            }

            dmClearSurface(screen, dmMapRGB(screen, 255, 255, 150));
            dmFillRect(screen, 0, 0, screen->w, TTF_FontHeight(font) + 10, dmMapRGB(screen, 50, 50, 150));
            dmDrawTTFText(screen, font, fontcol, 5, 5, "%3d x %3d @ 0x%08x, skip=%d/0x%x",
                scrWidth, scrHeight, scrOffs, scrSkip, scrSkip);

            dmFillRect(screen, 0, screen->h - TTF_FontHeight(font) - 10, screen->w, screen->h, dmMapRGB(screen, 150, 50, 50));
            if (scrPalette)
            {
                dmDrawTTFText(screen, font, fontcol, 5, screen->h - TTF_FontHeight(font) - 5,
                "Palette offset 0x%08x/%08x", scrPalOffs, scrSize);
            }
            else
            {
                dmDrawTTFText(screen, font, fontcol, 5, screen->h - TTF_FontHeight(font) - 5,
                "Generated palette.");
            }
            dmDrawTTFText(screen, font, fontcol, 450, screen->h - TTF_FontHeight(font) - 5,
                "useRLE=%d", useRLE);
            
            
            if (showTest)
                DM_Random(bmap, SDL_GetTicks() / 100);
            else
                DM_Redraw(bmap, scrData + scrOffs, scrSkip, useRLE, 0xc0);

//            float f = SDL_GetTicks() / 200.0f;
//            dmScaledBlitSurfaceAny(bmap, sin(f) * 50, 40, screen->w + 100 * cos(f), screen->h - 80, screen, DMD_NONE);
            dmScaledBlitSurfaceAny(bmap, 5, 40, screen->w - 10, screen->h - 80, screen, DMD_NONE);

            if (showHex)
            {
                int w = 350, h = screen->h - 50;
                int i, x = screen->w - w, y = 25;
                int fh = TTF_FontHeight(font);
                
                dmFillRect(screen, screen->w - 350,  - 5, w, h, dmMapRGB(screen, 50, 50, 50));
                
                dmDrawTTFText(screen, font, fontcol, x, y, "Palette hexdump");
                y += fh + 5;
                for (i = 0; i < 16; i++)
                {
                    int offs = scrPalOffs + i * 3;
                    dmDrawTTFText(screen, font, fontcol, x, y + fh * i, "%04x: %02x %02x %02x | '%c' '%c' '%c'",
                        offs, scrData[offs], scrData[offs+1], scrData[offs+2],
                        scrData[offs], scrData[offs+1], scrData[offs+2]);
                }
            }

            if (SDL_MUSTLOCK(screen) != 0)
                SDL_UnlockSurface(screen);

            SDL_Flip(screen);
            needRedraw = FALSE;
        }
        
        SDL_Delay(10);
    }


error_exit:
    if (screen)
        SDL_FreeSurface(screen);

    if (font)
        TTF_CloseFont(font);

    if (initSDL)
        SDL_Quit();

    if (initTTF)
        TTF_Quit();

    return 0;
}