/*
* src/sysvid.c
*
* Copyright (C) 1998-2002 BigOrno (bigorno@bigorno.net). All rights reserved.
*
* The use and distribution terms for this software are contained in the file
* named README, which can be found in the root of this distribution. By
* using this software in any fashion, you are agreeing to be bound by the
* terms of this license.
*
* You must not remove this notice, or any other, from this software.
*/
#include <malloc.h> // malloc
#include <memory.h> // memset
#include <SDL.h>
#include "system.h"
#include "game.h"
#include "img.h"
#define SYSVID_WIDTH 640
#define SYSVID_HEIGHT 480
#define SYSVID_BPP 32
U8 *sysvid_fb; // frame buffer
U8 want_fullscreen = TRUE;
U8 want_filter = TRUE;
U8 redraw_screen = FALSE;
static SDL_Surface *screen;
// Initialise video
void sysvid_init (void)
{
// create frame buffer
sysvid_fb
= malloc (320 * 200);
if (sysvid_fb == NULL)
sys_panic ("Fatal error: frame buffer allocation failed.\n");
// SDL init
if (SDL_Init (SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
sys_panic ("Fatal error: could not initialize SDL.\n");
SDL_WM_SetCaption ("Rick Dangerous", "Rick Dangerous");
SDL_ShowCursor (SDL_DISABLE);
// check video modes
if (SDL_ListModes (NULL, SDL_FULLSCREEN) == 0)
sys_panic ("Fatal error: SDL can not find an appropriate video mode.\n");
// set video mode
screen = SDL_SetVideoMode (SYSVID_WIDTH, SYSVID_HEIGHT, SYSVID_BPP, (want_fullscreen ? SDL_FULLSCREEN : 0));
}
// Shutdown video
void sysvid_shutdown (void)
{
// destroy frame buffer
if (sysvid_fb)
sysvid_fb = NULL;
// SDL quit
SDL_Quit ();
}
// Clear screen
void sysvid_clear (void)
{
memset (sysvid_fb
, 0, 320 * 200);
}
// Update screen
void sysvid_paint (rect_t *rects)
{
static SDL_Rect area;
static rect_t rect_screen = {0, 0, 320, 200, NULL};
static int pixel_size = SYSVID_BPP / 8;
static int zoom = SYSVID_WIDTH / 320;
static U8 palette[16][3] =
{
{0x00, 0x00, 0x00},
{0xd8, 0x00, 0x00},
{0xb0, 0x6c, 0x68},
{0xf8, 0x90, 0x68},
{0x20, 0x24, 0x20},
{0x00, 0x48, 0xb0},
{0x00, 0x6c, 0xd8},
{0x20, 0x48, 0x00},
{0x48, 0x6c, 0x20},
{0x48, 0x24, 0x00},
{0x90, 0x48, 0x00},
{0xd8, 0x6c, 0x00},
{0x48, 0x48, 0x48},
{0x68, 0x6c, 0x68},
{0x90, 0x90, 0x90},
{0xb0, 0xb4, 0xb0}
};
U16 x, y, xz, yz;
U8 *p, *q, *p0, *q0;
if (rects == NULL)
return;
if (redraw_screen)
{
redraw_screen = FALSE;
screen = SDL_SetVideoMode (SYSVID_WIDTH, SYSVID_HEIGHT, SYSVID_BPP, (want_fullscreen ? SDL_FULLSCREEN : 0));
sysvid_paint (&rect_screen);
}
while (rects)
{
p0 = sysvid_fb;
p0 += rects->x + rects->y * 320;
q0 = (U8 *)screen->pixels;
q0 += (pixel_size * rects->x + pixel_size * (rects->y + 20) * 320 * zoom) * zoom;
for (y = (rects->y + 20); y < (rects->y + 20) + rects->height; y++)
{
for (yz = 0; yz < zoom; yz++)
{
p = p0;
q = q0;
for (x = rects->x; x < rects->x + rects->width; x++)
{
for (xz = 0; xz < zoom; xz++)
{
if (want_filter && (y + yz < 220))
{
*(q + 0) = (U8) (( (U32) ((zoom - xz) * (U32) palette[*( p )][2]
+ xz * (U32) palette[*( p + 1 )][2])
+ (U32) ((zoom - yz) * (U32) palette[*( p )][2]
+ yz * (U32) palette[*(p + 320)][2]))
/ (zoom * zoom));
*(q + 1) = (U8) (( (U32) ((zoom - xz) * (U32) palette[*( p )][1]
+ xz * (U32) palette[*( p + 1 )][1])
+ (U32) ((zoom - yz) * (U32) palette[*( p )][1]
+ yz * (U32) palette[*(p + 320)][1]))
/ (zoom * zoom));
*(q + 2) = (U8) (( (U32) ((zoom - xz) * (U32) palette[*( p )][0]
+ xz * (U32) palette[*( p + 1 )][0])
+ (U32) ((zoom - yz) * (U32) palette[*( p )][0]
+ yz * (U32) palette[*(p + 320)][0]))
/ (zoom * zoom));
*(q + 3) = 0;
}
else
{
*(q + 0) = palette[*p][2];
*(q + 1) = palette[*p][1];
*(q + 2) = palette[*p][0];
*(q + 3) = 0;
}
q += pixel_size;
}
p++;
}
q0 += 320 * pixel_size * zoom;
}
p0 += 320;
}
area.x = rects->x * zoom;
area.y = (rects->y + 20) * zoom;
area.h = rects->height * zoom;
area.w = rects->width * zoom;
SDL_UpdateRects (screen, 1, &area);
rects = rects->next;
}
}