view pwplib/sdl.c @ 40:32559c69f6e5

Cosmetics.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 24 May 2010 02:55:17 +0300
parents d83239a98d1e
children ea44e1d9eb7c
line wrap: on
line source

/*
 * pwplib SDL (Simple Directmedia Layer) video "driver"
 * (C) Copyright 2010 ccr/TNSP^PWP <ccr@tnsp.org>
 *
 * Rasterization based on the prototype X11 driver by viznut/PWP
 *
 * This file and other changes are distributed under same
 * license as pwplib itself.
 */
#include "config.h"

#ifdef DRIVE_SDL

#include "pwplib.h"
#include <SDL.h>

#define PWP_WINNAME "pwplib"
#define PWP_NCOLORS 256

struct {
    int width, height, vflags;
    SDL_Surface *screen;
    SDL_Color pal[PWP_NCOLORS];
    Uint32 lookup[PWP_NCOLORS];
} pwp_SDL;


static void pwp_SDL_dump_rast_4x4()
{
    Uint8 *dst = pwp_SDL.screen->pixels;
    Uint8 *src = pwplib.videobuf.d;
    int y;

    if (SDL_MUSTLOCK(pwp_SDL.screen) != 0)
    {
        if (SDL_LockSurface(pwp_SDL.screen) != 0)
        {
            SDL_Quit();
            pwpwrite("SDL: Could not lock video surface!\n");
            exit(1);
        }
    }

    for (y = pwplib.videobuf.height; y; y--)
    {
        int i;
        Uint8 *dsrc = dst;
        Uint32 *d = (Uint32 *)dst;
        Uint8 *s = src;

        for (i = pwplib.videobuf.width; i; i--)
            *d++ = pwp_SDL.lookup[*s++];

        dst += pwp_SDL.screen->pitch;

        /* Optimization: memcpy the rasterized line 3 times below it */
        for (i = 3; i; i--)
        {
            memcpy(dst, dsrc, pwp_SDL.screen->pitch);
            dst += pwp_SDL.screen->pitch;
        }

        src += pwplib.videobuf.width;
    }

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

    SDL_Flip(pwp_SDL.screen);
}

static void rast2rgb(int n, int muller, int *r, int *g, int *b)
{
    int fg = n & 15, bg = (n >> 4) & 15;
    static const char rgb[16 * 3] = { 0, 0, 0,
        0, 0, 9,
        0, 9, 0,
        0, 9, 9,
        9, 0, 0,
        9, 0, 9,
        9, 9, 0,
        9, 9, 9,
        6, 6, 6,
        0, 0, 15,
        0, 15, 0,
        0, 15, 15,
        15, 0, 0,
        15, 0, 15,
        15, 15, 0,
        15, 15, 15
    };

    *r = (muller * (rgb[bg * 3 + 0] * 2 + rgb[fg * 3 + 0])) / 45;
    *g = (muller * (rgb[bg * 3 + 1] * 2 + rgb[fg * 3 + 1])) / 45;
    *b = (muller * (rgb[bg * 3 + 2] * 2 + rgb[fg * 3 + 2])) / 45;
}

int pwp_SDL_init(void)
{
    int i;

    /* Assume these settings for now */
    pwp_SDL.vflags = pwplib.setup[SETUP_FULLSCREEN] ? SDL_FULLSCREEN : 0;
    pwp_SDL.width = pwplib.setup[SETUP_XRES];
    pwp_SDL.height = pwplib.setup[SETUP_YRES];

    if (pwp_SDL.width < 8 || pwp_SDL.height < 16) {
        pwpwrite("* invalid xres or yres (%d x %d)\n", pwp_SDL.width, pwp_SDL.height);
        return 0;
    }

    /* Set pwplib internal parameters */
    pwplib.videobuf.width = pwp_SDL.width / 4;
    pwplib.videobuf.height = pwp_SDL.height / 4;
    pwplib.dump_rast = pwp_SDL_dump_rast_4x4;

    /* Initialize a indexed / paletted video surface */
    pwp_SDL.screen = SDL_SetVideoMode(pwp_SDL.width, pwp_SDL.height, 8, pwp_SDL.vflags);
    if (pwp_SDL.screen == NULL) {
        pwpwrite("* SDL could not initialize video surface/mode.\n");
        return 0;
    }
    
    /* Set window caption, if any, hide mouse cursor */
    SDL_WM_SetCaption(PWP_WINNAME, PWP_WINNAME);
    SDL_ShowCursor(0);

    /* Generate palette and rasterization lookup table */
    for (i = 0; i < PWP_NCOLORS; i++)
    {
        int r, g, b;
        rast2rgb(i, 255, &r, &g, &b);
        pwp_SDL.pal[i].r = r;
        pwp_SDL.pal[i].g = g;
        pwp_SDL.pal[i].b = b;
        pwp_SDL.lookup[i] = i | (i << 8) | (i << 16) | (i << 24);
    }
    SDL_SetColors(pwp_SDL.screen, pwp_SDL.pal, 0, PWP_NCOLORS);

    pwpwrite("* SDL video (%d x %d, pitch=%d)\n", pwp_SDL.screen->w, pwp_SDL.screen->h, pwp_SDL.screen->pitch);

    return 1;
}

#endif