view vview.c @ 0:32250b436bca

Initial re-import.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 28 Sep 2012 01:54:23 +0300
parents
children daeb5d4f6bad
line wrap: on
line source

#include "dmlib.h"
#include "dmargs.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;
}