home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Large Pack of OldSkool DOS MOD Trackers
/
goattracker_2.68.zip
/
src
/
bme
/
bme_gfx.c
< prev
next >
Wrap
C/C++ Source or Header
|
2008-04-01
|
14KB
|
566 lines
//
// BME (Blasphemous Multimedia Engine) graphics main module
//
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <SDL/SDL.h>
#include "bme_main.h"
#include "bme_cfg.h"
#include "bme_win.h"
#include "bme_io.h"
#include "bme_err.h"
// Prototypes
int gfx_init(unsigned xsize, unsigned ysize, unsigned framerate, unsigned flags);
int gfx_reinit(void);
void gfx_uninit(void);
int gfx_lock(void);
void gfx_unlock(void);
void gfx_flip(void);
void gfx_setclipregion(unsigned left, unsigned top, unsigned right, unsigned bottom);
void gfx_setmaxspritefiles(int num);
void gfx_setmaxcolors(int num);
int gfx_loadpalette(char *name);
void gfx_calcpalette(int fade, int radd, int gadd, int badd);
void gfx_setpalette(void);
int gfx_loadblocks(char *name);
int gfx_loadsprites(int num, char *name);
void gfx_freesprites(int num);
void gfx_drawsprite(int x, int y, unsigned num);
void gfx_getspriteinfo(unsigned num);
int gfx_initted = 0;
int gfx_redraw = 0;
int gfx_fullscreen = 0;
int gfx_scanlinemode = 0;
int gfx_preventswitch = 0;
int gfx_virtualxsize;
int gfx_virtualysize;
int gfx_windowxsize;
int gfx_windowysize;
int gfx_blockxsize = 16;
int gfx_blockysize = 16;
int spr_xsize = 0;
int spr_ysize = 0;
int spr_xhotspot = 0;
int spr_yhotspot = 0;
unsigned gfx_nblocks = 0;
Uint8 gfx_palette[MAX_COLORS * 3] = {0};
SDL_Surface *gfx_screen = NULL;
// Static variables
static int gfx_initexec = 0;
static unsigned gfx_last_xsize;
static unsigned gfx_last_ysize;
static unsigned gfx_last_framerate;
static unsigned gfx_last_flags;
static int gfx_cliptop;
static int gfx_clipbottom;
static int gfx_clipleft;
static int gfx_clipright;
static int gfx_maxcolors = MAX_COLORS;
static int gfx_maxspritefiles = 0;
static SPRITEHEADER **gfx_spriteheaders = NULL;
static Uint8 **gfx_spritedata = NULL;
static unsigned *gfx_spriteamount = NULL;
static SDL_Color gfx_sdlpalette[MAX_COLORS];
static int gfx_locked = 0;
int gfx_init(unsigned xsize, unsigned ysize, unsigned framerate, unsigned flags)
{
int sdlflags = SDL_HWSURFACE;
// Prevent re-entry (by window procedure)
if (gfx_initexec) return BME_OK;
gfx_initexec = 1;
gfx_last_xsize = xsize;
gfx_last_ysize = ysize;
gfx_last_framerate = framerate;
gfx_last_flags = flags & ~(GFX_FULLSCREEN | GFX_WINDOW);
// Store the options contained in the flags
gfx_scanlinemode = flags & (GFX_SCANLINES | GFX_DOUBLESIZE);
if (flags & GFX_NOSWITCHING) gfx_preventswitch = 1;
else gfx_preventswitch = 0;
if (win_fullscreen) sdlflags |= SDL_FULLSCREEN;
if (flags & GFX_FULLSCREEN) sdlflags |= SDL_FULLSCREEN;
if (flags & GFX_WINDOW) sdlflags &= ~SDL_FULLSCREEN;
if (sdlflags & SDL_FULLSCREEN) gfx_fullscreen = 1;
else gfx_fullscreen = 0;
// Calculate virtual window size
gfx_virtualxsize = xsize;
gfx_virtualxsize /= 16;
gfx_virtualxsize *= 16;
gfx_virtualysize = ysize;
if ((!gfx_virtualxsize) || (!gfx_virtualysize))
{
gfx_initexec = 0;
gfx_uninit();
bme_error = BME_ILLEGAL_CONFIG;
return BME_ERROR;
}
// Calculate actual window size (for scanline mode & doublesize mode
// this is double the virtual)
gfx_windowxsize = gfx_virtualxsize;
gfx_windowysize = gfx_virtualysize;
if (gfx_scanlinemode)
{
gfx_windowxsize <<= 1;
gfx_windowysize <<= 1;
}
gfx_setclipregion(0, 0, gfx_virtualxsize, gfx_virtualysize);
// Colors 0 & 255 are always black & white
gfx_sdlpalette[0].r = 0;
gfx_sdlpalette[0].g = 0;
gfx_sdlpalette[0].b = 0;
gfx_sdlpalette[255].r = 255;
gfx_sdlpalette[255].g = 255;
gfx_sdlpalette[255].b = 255;
gfx_screen = SDL_SetVideoMode(gfx_windowxsize, gfx_windowysize, 8, sdlflags);
gfx_initexec = 0;
if (gfx_screen)
{
gfx_initted = 1;
gfx_redraw = 1;
gfx_setpalette();
win_setmousemode(win_mousemode);
return BME_OK;
}
else return BME_ERROR;
}
int gfx_reinit(void)
{
return gfx_init(gfx_last_xsize, gfx_last_ysize, gfx_last_framerate,
gfx_last_flags);
}
void gfx_uninit(void)
{
gfx_initted = 0;
return;
}
int gfx_lock(void)
{
if (gfx_locked) return 1;
if (!gfx_initted) return 0;
if (!SDL_LockSurface(gfx_screen))
{
gfx_locked = 1;
return 1;
}
else return 0;
}
void gfx_unlock(void)
{
if (gfx_locked)
{
SDL_UnlockSurface(gfx_screen);
gfx_locked = 0;
}
}
void gfx_flip()
{
SDL_Flip(gfx_screen);
gfx_redraw = 0;
}
void gfx_setmaxcolors(int num)
{
gfx_maxcolors = num;
}
int gfx_loadpalette(char *name)
{
int handle;
handle = io_open(name);
if (handle == -1)
{
bme_error = BME_OPEN_ERROR;
return BME_ERROR;
}
if (io_read(handle, gfx_palette, sizeof gfx_palette) != sizeof gfx_palette)
{
bme_error = BME_READ_ERROR;
io_close(handle);
return BME_ERROR;
}
io_close(handle);
gfx_calcpalette(64, 0, 0, 0);
bme_error = BME_OK;
return BME_OK;
}
void gfx_calcpalette(int fade, int radd, int gadd, int badd)
{
Uint8 *sptr = &gfx_palette[3];
int c, cl;
if (radd < 0) radd = 0;
if (gadd < 0) gadd = 0;
if (badd < 0) badd = 0;
for (c = 1; c < 255; c++)
{
cl = *sptr;
cl *= fade;
cl >>= 6;
cl += radd;
if (cl > 63) cl = 63;
if (cl < 0) cl = 0;
gfx_sdlpalette[c].r = (cl << 2) | (cl & 3);
sptr++;
cl = *sptr;
cl *= fade;
cl >>= 6;
cl += gadd;
if (cl > 63) cl = 63;
if (cl < 0) cl = 0;
gfx_sdlpalette[c].g = (cl << 2) | (cl & 3);
sptr++;
cl = *sptr;
cl *= fade;
cl >>= 6;
cl += badd;
if (cl > 63) cl = 63;
if (cl < 0) cl = 0;
gfx_sdlpalette[c].b = (cl << 2) | (cl & 3);
sptr++;
}
}
void gfx_setpalette(void)
{
if (!gfx_initted) return;
SDL_SetColors(gfx_screen, &gfx_sdlpalette[0], 0, gfx_maxcolors);
}
void gfx_setclipregion(unsigned left, unsigned top, unsigned right, unsigned bottom)
{
if (left >= right) return;
if (top >= bottom) return;
if (left >= gfx_virtualxsize) return;
if (top >= gfx_virtualysize) return;
if (right > gfx_virtualxsize) return;
if (bottom > gfx_virtualysize) return;
gfx_clipleft = left;
gfx_clipright = right;
gfx_cliptop = top;
gfx_clipbottom = bottom;
}
void gfx_setmaxspritefiles(int num)
{
if (num <= 0) return;
if (gfx_spriteheaders) return;
gfx_spriteheaders = malloc(num * sizeof(Uint8 *));
gfx_spritedata = malloc(num * sizeof(Uint8 *));
gfx_spriteamount = malloc(num * sizeof(unsigned));
if ((gfx_spriteheaders) && (gfx_spritedata) && (gfx_spriteamount))
{
int c;
gfx_maxspritefiles = num;
for (c = 0; c < num; c++)
{
gfx_spriteamount[c] = 0;
gfx_spritedata[c] = NULL;
gfx_spriteheaders[c] = NULL;
}
}
else gfx_maxspritefiles = 0;
}
int gfx_loadsprites(int num, char *name)
{
int handle, size, c;
int datastart;
if (!gfx_spriteheaders)
{
gfx_setmaxspritefiles(DEFAULT_MAX_SPRFILES);
}
bme_error = BME_OPEN_ERROR;
if (num >= gfx_maxspritefiles) return BME_ERROR;
gfx_freesprites(num);
handle = io_open(name);
if (handle == -1) return BME_ERROR;
size = io_lseek(handle, 0, SEEK_END);
io_lseek(handle, 0, SEEK_SET);
gfx_spriteamount[num] = io_readle32(handle);
gfx_spriteheaders[num] = malloc(gfx_spriteamount[num] * sizeof(SPRITEHEADER));
if (!gfx_spriteheaders[num])
{
bme_error = BME_OUT_OF_MEMORY;
io_close(handle);
return BME_ERROR;
}
for (c = 0; c < gfx_spriteamount[num]; c++)
{
SPRITEHEADER *hptr = gfx_spriteheaders[num] + c;
hptr->xsize = io_readle16(handle);
hptr->ysize = io_readle16(handle);
hptr->xhot = io_readle16(handle);
hptr->yhot = io_readle16(handle);
hptr->offset = io_readle32(handle);
}
datastart = io_lseek(handle, 0, SEEK_CUR);
gfx_spritedata[num] = malloc(size - datastart);
if (!gfx_spritedata[num])
{
bme_error = BME_OUT_OF_MEMORY;
io_close(handle);
return BME_ERROR;
}
io_read(handle, gfx_spritedata[num], size - datastart);
io_close(handle);
bme_error = BME_OK;
return BME_OK;
}
void gfx_freesprites(int num)
{
if (num >= gfx_maxspritefiles) return;
if (gfx_spritedata[num])
{
free(gfx_spritedata[num]);
gfx_spritedata[num] = NULL;
}
if (gfx_spriteheaders[num])
{
free(gfx_spriteheaders[num]);
gfx_spriteheaders[num] = NULL;
}
}
void gfx_copyscreen8(Uint8 *destaddress, Uint8 *srcaddress, unsigned pitch)
{
int c, d;
switch(gfx_scanlinemode)
{
default:
for (c = 0; c < gfx_virtualysize; c++)
{
memcpy(destaddress, srcaddress, gfx_virtualxsize);
destaddress += pitch;
srcaddress += gfx_virtualxsize;
}
break;
case GFX_SCANLINES:
for (c = 0; c < gfx_virtualysize; c++)
{
d = gfx_virtualxsize;
while (d--)
{
*destaddress = *srcaddress;
destaddress++;
*destaddress = *srcaddress;
destaddress++;
srcaddress++;
}
destaddress += pitch*2 - (gfx_virtualxsize << 1);
}
break;
case GFX_DOUBLESIZE:
for (c = 0; c < gfx_virtualysize; c++)
{
d = gfx_virtualxsize;
while (d--)
{
*destaddress = *srcaddress;
destaddress++;
*destaddress = *srcaddress;
destaddress++;
srcaddress++;
}
destaddress += pitch - (gfx_virtualxsize << 1);
srcaddress -= gfx_virtualxsize;
d = gfx_virtualxsize;
while (d--)
{
*destaddress = *srcaddress;
destaddress++;
*destaddress = *srcaddress;
destaddress++;
srcaddress++;
}
destaddress += pitch - (gfx_virtualxsize << 1);
}
break;
}
}
void gfx_getspriteinfo(unsigned num)
{
unsigned sprf = num >> 16;
unsigned spr = (num & 0xffff) - 1;
SPRITEHEADER *hptr;
if ((sprf >= gfx_maxspritefiles) || (!gfx_spriteheaders[sprf]) ||
(spr >= gfx_spriteamount[sprf])) hptr = NULL;
else hptr = gfx_spriteheaders[sprf] + spr;
if (!hptr)
{
spr_xsize = 0;
spr_ysize = 0;
spr_xhotspot = 0;
spr_yhotspot = 0;
return;
}
spr_xsize = hptr->xsize;
spr_ysize = hptr->ysize;
spr_xhotspot = hptr->xhot;
spr_yhotspot = hptr->yhot;
}
void gfx_drawsprite(int x, int y, unsigned num)
{
unsigned sprf = num >> 16;
unsigned spr = (num & 0xffff) - 1;
SPRITEHEADER *hptr;
if (!gfx_initted) return;
if (!gfx_locked) return;
Uint8 *sptr;
Uint8 *dptr;
int cx;
if ((sprf >= gfx_maxspritefiles) || (!gfx_spriteheaders[sprf]) ||
(spr >= gfx_spriteamount[sprf]))
{
spr_xsize = 0;
spr_ysize = 0;
spr_xhotspot = 0;
spr_yhotspot = 0;
return;
}
else hptr = gfx_spriteheaders[sprf] + spr;
sptr = gfx_spritedata[sprf] + hptr->offset;
spr_xsize = hptr->xsize;
spr_ysize = hptr->ysize;
spr_xhotspot = hptr->xhot;
spr_yhotspot = hptr->yhot;
x -= spr_xhotspot;
y -= spr_yhotspot;
if (x >= gfx_clipright) return;
if (y >= gfx_clipbottom) return;
if (x + spr_xsize <= gfx_clipleft) return;
if (y + spr_ysize <= gfx_cliptop) return;
while (y < gfx_cliptop)
{
int dec = *sptr++;
if (dec == 255)
{
if (!(*sptr)) return;
y++;
}
else
{
if (dec < 128)
{
sptr += dec;
}
}
}
while (y < gfx_clipbottom)
{
int dec;
cx = x;
dptr = gfx_screen->pixels + y * gfx_screen->pitch + x;
for (;;)
{
dec = *sptr++;
if (dec == 255)
{
if (!(*sptr)) return;
y++;
break;
}
if (dec < 128)
{
if ((cx + dec <= gfx_clipleft) || (cx >= gfx_clipright))
{
goto SKIP;
}
if (cx < gfx_clipleft)
{
dec -= (gfx_clipleft - cx);
sptr += (gfx_clipleft - cx);
dptr += (gfx_clipleft - cx);
cx = gfx_clipleft;
}
while ((cx < gfx_clipright) && (dec))
{
*dptr = *sptr;
cx++;
sptr++;
dptr++;
dec--;
}
SKIP:
cx += dec;
sptr += dec;
dptr += dec;
}
else
{
cx += (dec & 0x7f);
dptr += (dec & 0x7f);
}
}
}
}