view pwplib/sdl.c @ 71:a87eb778f225

Improvements to the MinGW crossbuild. Should now build with default tools from Debian mingw packages, though you need Win32 version of libSDL with the necessary headers and so on in addition. 64-bit builds not tested and probably won't work. Tested on Debian 7.0, earlier won't work. binutils-mingw-w64-i686 gcc-mingw-w64-i686 mingw-w64-i686-dev
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 14 Aug 2012 03:08:10 +0300
parents 32559c69f6e5
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