view pwplib/sdl.c @ 11:2105d2dfefa3

Try to adjust blitting with SDL surface pitch. Might fix something.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 18 May 2010 18:47:16 +0300
parents acb5694e93d9
children 18e14722f58a
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 cols[PWP_NCOLORS];
    u32 lookup[256];
} pwp_SDL;


static void pwp_SDL_dump_rast_4x4()
{
    u32 *d = (u32 *) pwp_SDL.screen->pixels;
    int x, y, j = 0;
    u8 *ss = (u8 *) pwplib.videobuf.d;

    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 * 2; y; y--)
    {
        u8 *s = ss;

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

        j = (j + 1) & 1;
        if (!j)
            ss += pwplib.videobuf.width;
        
        if (pwp_SDL.screen->pitch > pwp_SDL.screen->w)
            d += pwp_SDL.screen->pitch - pwp_SDL.screen->w;
    }

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

void pwp_SDL_close(void)
{
    SDL_Quit();
}

int pwp_SDL_init(void)
{
    int pal[PWP_NCOLORS * 3], i;

    /* Assume these settings for now */
    pwp_SDL.vflags = 0;
    pwp_SDL.width = 640;
    pwp_SDL.height = 480;

    /* 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;

    /* NOTICE! Here we assume that SDL audio will be used also .. this is kind of a hack,
     * because obviously we cannot know what audio subsystem is used at this point.
     * (Blame oversimplicity of pwplib)
     * -- ccr
     */
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTTHREAD | SDL_INIT_AUDIO) != 0)
    {
        pwpwrite("* SDL could not be initialized.\n");
        return 0;
    }

    pwp_regdestr(pwp_SDL_close);

    /* 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)
    {
        SDL_Quit();
        pwpwrite("* SDL could not initialize video surface/mode.\n");
        return 0;
    }

    /* Set window caption, if any */
    SDL_WM_SetCaption(PWP_WINNAME, PWP_WINNAME);


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

    pwpwrite("* SDL\n");

    return 1;
}

#endif