Engine changes vs the vendored upstream (full ledger in docs/upstream-patches.md): - Assets: replace the encrypted FILE000N.GLB archives with a catalog of pre-decrypted loose files (data/INDEX); GLB_SlotItems() drives mission-pack / registered-version detection; payloads never run the GLB cipher at runtime. - Platform: Linux/SDL2/ALSA only; Android, MSVC/MinGW, macOS packaging, bundled Windows SDL2 SDKs and the ENDOOM exit screen are gone; EXIT_Error now prints before exiting. - Rendering: decouple presentation from simulation -- sim stays at the original 70/3 Hz, frames render interpolated at display rate (player, map scroll, enemies, shots, bonuses, anims, shadows); menus keep 70 Hz pacing; vsync with a delay-guard fallback. - QoL: borderless window mode (Video/borderless), no menu cursor snapping onto default buttons. Fix four regressions from the render split: - Shield bars never redrew: RAP_ThinkStats latches g_oldshield each sim step before RAP_DisplayStats' dirty check could fire. Bars now draw unconditionally per rendered frame; g_oldsuper deleted, g_oldshield kept as sim-side damage-detection state only. - Dying ships despawned without exploding: the render loop never called ANIMS_DisplayHigh(); most air-death explosions register HIGH_AIR. Restored between the player and enemy shots, as upstream orders it. - Laser turret broke: reusing doneflag as a draw marker (it is hit/retire game state, and the turret retire path never frees its shot) hid the beam on hitting ticks and leaked one SHOTS pool slot per fire until no weapon could shoot. S_LINE tracers now carry an age counter: one Think pass, every render of their birth step, purged at the top of the next Think. - Muzzle flash was cleared per rendered frame, making it invisible at display refresh rates; now cleared once per simulation step.
1710 lines
43 KiB
C++
1710 lines
43 KiB
C++
#include <string.h>
|
|
#include <stdint.h>
|
|
#include "SDL.h"
|
|
#include "common.h"
|
|
#include "gfxapi.h"
|
|
#include "i_video.h"
|
|
#include "entypes.h"
|
|
|
|
char *displaybuffer;
|
|
char *displayscreen;
|
|
|
|
int framecount;
|
|
|
|
int ylookup[200];
|
|
|
|
char *ltable, *dtable, *gtable;
|
|
char tpal1[768], tpal2[768];
|
|
int start_lookup = 0;
|
|
int end_lookup = 255;
|
|
char *gfx_inmem;
|
|
int gfx_xp, gfx_yp;
|
|
int gfx_lx, gfx_ly;
|
|
int gfx_imga;
|
|
|
|
int tablelen;
|
|
int stable[324];
|
|
|
|
int ud_x, ud_y, ud_lx, ud_ly;
|
|
int o_ud_x, o_ud_y, o_ud_lx, o_ud_ly;
|
|
int update_start;
|
|
|
|
void (*framehook)(void (*call)(void));
|
|
|
|
static int timer_init = 0;
|
|
|
|
int retraceflag = 1;
|
|
int fontspacing = 1;
|
|
|
|
int G3D_x; // input: x position
|
|
int G3D_y; // input: y position
|
|
int G3D_z; // input: z position
|
|
int G3D_screenx; // output: screen x pos
|
|
int G3D_screeny; // output: screen y pos
|
|
int G3D_viewx; // user view x pos
|
|
int G3D_viewy; // user view y pos
|
|
int G3D_viewz; // user view z pos
|
|
|
|
void GFX_InitTimer(void)
|
|
{
|
|
#if SDL_VERSION_ATLEAST(2, 0, 5)
|
|
SDL_SetHint(SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING, "1");
|
|
#endif
|
|
SDL_Init(SDL_INIT_TIMER);
|
|
timer_init = 1;
|
|
}
|
|
|
|
#define GFX_RATE 70
|
|
|
|
/***************************************************************************
|
|
GFX_UpdateTimer () -
|
|
***************************************************************************/
|
|
void
|
|
GFX_UpdateTimer(
|
|
void
|
|
)
|
|
{
|
|
if (!timer_init)
|
|
return;
|
|
|
|
static int last;
|
|
static int accm;
|
|
int now = SDL_GetTicks();
|
|
|
|
if (last == 0)
|
|
last = now;
|
|
|
|
for (int i = last; i < now;)
|
|
{
|
|
int step = (1000 - accm + (GFX_RATE - 1)) / GFX_RATE;
|
|
|
|
if (step < 1)
|
|
step = 1;
|
|
|
|
if (step > now - i)
|
|
step = now - i;
|
|
|
|
accm += GFX_RATE * step;
|
|
|
|
while (accm >= 1000)
|
|
{
|
|
accm -= 1000;
|
|
framecount++;
|
|
}
|
|
|
|
i += step;
|
|
}
|
|
|
|
last = now;
|
|
}
|
|
|
|
/***************************************************************************
|
|
GFX_GetFrameCount () -
|
|
***************************************************************************/
|
|
int
|
|
GFX_GetFrameCount(
|
|
void
|
|
)
|
|
{
|
|
I_GetEvent();
|
|
GFX_UpdateTimer();
|
|
|
|
return framecount;
|
|
}
|
|
|
|
/***************************************************************************
|
|
GFX_SetInterp () - Sets the interpolation fraction (num/den, 0 <= num <=
|
|
den) used by GFX_InterpCoord() for this rendered frame.
|
|
***************************************************************************/
|
|
static int gfx_interp_num = 1, gfx_interp_den = 1;
|
|
|
|
void
|
|
GFX_SetInterp(
|
|
int num, // INPUT : interpolated fraction numerator
|
|
int den // INPUT : interpolated fraction denominator
|
|
)
|
|
{
|
|
if (den > 0 && num >= 0)
|
|
{
|
|
gfx_interp_num = num;
|
|
gfx_interp_den = den;
|
|
}
|
|
}
|
|
|
|
/***************************************************************************
|
|
GFX_InterpCoord () - Interpolates between previous and current simulation
|
|
position: prev + (cur - prev) * num/den.
|
|
***************************************************************************/
|
|
int
|
|
GFX_InterpCoord(
|
|
int cur, // INPUT : current sim position
|
|
int prev // INPUT : previous sim position
|
|
)
|
|
{
|
|
return prev + (int)(((long long)(cur - prev) * gfx_interp_num) / gfx_interp_den);
|
|
}
|
|
|
|
/*************************************************************************
|
|
GFX_ClipLines ()
|
|
*************************************************************************/
|
|
int // RETURN: 0 = Off, 1 == No Clip , 2 == Cliped
|
|
GFX_ClipLines(
|
|
char **image, // INOUT : pointer to image or NUL
|
|
int *x, // INOUT : pointer to x pos
|
|
int *y, // INOUT : pointer to y pos
|
|
int *lx, // INOUT : pointer to width
|
|
int *ly // INOUT : pointer to length
|
|
)
|
|
{
|
|
int rval = 1;
|
|
|
|
if (*x >= SCREENWIDTH)
|
|
return 0;
|
|
if (*y >= SCREENHEIGHT)
|
|
return 0;
|
|
if (*x + *lx <= 0)
|
|
return 0;
|
|
if (*y + *ly <= 0)
|
|
return 0;
|
|
|
|
if (*y < 0)
|
|
{
|
|
rval = 2;
|
|
if (image)
|
|
*image += -(*y) * *lx;
|
|
*ly += *y;
|
|
*y = 0;
|
|
}
|
|
|
|
if (*y + *ly > SCREENHEIGHT)
|
|
{
|
|
rval = 2;
|
|
*ly = SCREENHEIGHT - *y;
|
|
}
|
|
|
|
if (*x < 0)
|
|
{
|
|
rval = 2;
|
|
if (image)
|
|
*image += -(*x);
|
|
*lx += *x;
|
|
*x = 0;
|
|
}
|
|
|
|
if (*x + *lx > SCREENWIDTH)
|
|
{
|
|
rval = 2;
|
|
*lx = SCREENWIDTH - *x;
|
|
}
|
|
|
|
return rval;
|
|
}
|
|
|
|
/**************************************************************************
|
|
GFX_SetPalette() - Sets VGA palette
|
|
**************************************************************************/
|
|
void
|
|
GFX_SetPalette(
|
|
char *palette,
|
|
int start_pal
|
|
)
|
|
{
|
|
#if 0
|
|
if (retraceflag)
|
|
{
|
|
I_GetEvent();
|
|
GFX_UpdateTimer();
|
|
int now = framecount;
|
|
while (now == framecount)
|
|
GFX_UpdateTimer();
|
|
}
|
|
#endif
|
|
|
|
I_SetPalette((uint8_t*)palette, start_pal);
|
|
}
|
|
|
|
/**************************************************************************
|
|
GFX_InitSystem() - allocates buffers, makes tables, does not set vmode
|
|
**************************************************************************/
|
|
void
|
|
GFX_InitSystem(
|
|
void
|
|
)
|
|
{
|
|
displaybuffer = (char*)malloc(64000);
|
|
|
|
if (!displaybuffer)
|
|
{
|
|
EXIT_Error("GFX_Init() - malloc");
|
|
return;
|
|
}
|
|
|
|
memset(displaybuffer, 0, 64000);
|
|
|
|
GFX_InitTimer();
|
|
|
|
for (int loop = 0; loop < SCREENHEIGHT; loop++)
|
|
ylookup[loop] = loop * SCREENWIDTH;
|
|
|
|
ltable = (char*)malloc(256);
|
|
dtable = (char*)malloc(256);
|
|
gtable = (char*)malloc(256);
|
|
|
|
if (!ltable || !dtable || !gtable)
|
|
{
|
|
EXIT_Error("GFX_Init() - malloc");
|
|
return;
|
|
}
|
|
}
|
|
|
|
/**************************************************************************
|
|
GFX_InitVideo() - Inits things related to Video, and sets up fade tables
|
|
**************************************************************************/
|
|
void
|
|
GFX_InitVideo(
|
|
char *curpal
|
|
)
|
|
{
|
|
I_InitGraphics((uint8_t*)curpal);
|
|
displayscreen = (char*)I_VideoBuffer;
|
|
|
|
GFX_MakeLightTable(curpal, ltable, 9);
|
|
GFX_MakeLightTable(curpal, dtable, -9);
|
|
GFX_MakeGreyTable(curpal, gtable);
|
|
}
|
|
|
|
/**************************************************************************
|
|
GFX_EndSystem() - Frees up all resources used by GFX system
|
|
**************************************************************************/
|
|
void
|
|
GFX_EndSystem(
|
|
void
|
|
)
|
|
{
|
|
I_ShutdownGraphics();
|
|
}
|
|
|
|
/**************************************************************************
|
|
GFX_GetPalette() - Sets 256 color palette
|
|
**************************************************************************/
|
|
void
|
|
GFX_GetPalette(
|
|
char* curpal // OUTPUT : pointer to palette data
|
|
)
|
|
{
|
|
I_GetPalette((uint8_t*)curpal);
|
|
}
|
|
|
|
/**************************************************************************
|
|
GFX_FadeOut () - Fade Palette out to ( Red, Green , and Blue Value
|
|
**************************************************************************/
|
|
void
|
|
GFX_FadeOut(
|
|
int red, // INPUT : red ( 0 - 63 )
|
|
int green, // INPUT : green ( 0 - 63 )
|
|
int blue, // INPUT : blue ( 0 - 63 )
|
|
int steps // INPUT : steps of fade ( 0 - 255 )
|
|
)
|
|
{
|
|
char pal1[768];
|
|
char pal2[768];
|
|
int loop, i;
|
|
|
|
GFX_GetPalette(pal1);
|
|
memcpy(pal2, pal1, 768);
|
|
|
|
int now = GFX_GetFrameCount();
|
|
loop = 0;
|
|
|
|
while (GFX_GetFrameCount() - now < steps)
|
|
{
|
|
if (GFX_GetFrameCount() - now != loop)
|
|
{
|
|
loop = GFX_GetFrameCount() - now;
|
|
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
pal2[i * 3 + 0] = loop * (red - pal1[i * 3 + 0]) / steps + pal1[i * 3 + 0];
|
|
pal2[i * 3 + 1] = loop * (green - pal1[i * 3 + 1]) / steps + pal1[i * 3 + 1];
|
|
pal2[i * 3 + 2] = loop * (blue - pal1[i * 3 + 2]) / steps + pal1[i * 3 + 2];
|
|
}
|
|
|
|
GFX_SetPalette(pal2, 0);
|
|
I_FinishUpdate();
|
|
}
|
|
}
|
|
|
|
for (loop = 0; loop < 256; loop++)
|
|
{
|
|
pal2[loop * 3 + 0] = red;
|
|
pal2[loop * 3 + 1] = green;
|
|
pal2[loop * 3 + 2] = blue;
|
|
}
|
|
|
|
GFX_SetPalette(pal2, 0);
|
|
I_FinishUpdate();
|
|
}
|
|
|
|
/**************************************************************************
|
|
GFX_FadeIn () - Fades From current palette to new palette
|
|
**************************************************************************/
|
|
void
|
|
GFX_FadeIn(
|
|
char *palette, // INPUT : palette to fade into
|
|
int steps // INPUT : steps of fade ( 0 - 255 )
|
|
)
|
|
{
|
|
char pal1[768];
|
|
char pal2[768];
|
|
int loop, i;
|
|
|
|
GFX_GetPalette(pal1);
|
|
memcpy(pal2, pal1, 768);
|
|
|
|
int now = GFX_GetFrameCount();
|
|
loop = 0;
|
|
|
|
while (GFX_GetFrameCount() - now < steps)
|
|
{
|
|
if (GFX_GetFrameCount() - now != loop)
|
|
{
|
|
loop = GFX_GetFrameCount() - now;
|
|
|
|
for (i = 0; i < 768; i++)
|
|
{
|
|
pal2[i] = loop * (palette[i] - pal1[i]) / steps + pal1[i];
|
|
}
|
|
|
|
GFX_SetPalette(pal2, 0);
|
|
I_FinishUpdate();
|
|
}
|
|
}
|
|
|
|
GFX_SetPalette(palette, 0);
|
|
I_FinishUpdate();
|
|
}
|
|
|
|
/**************************************************************************
|
|
GFX_FadeStart () - Sets up fade for GFX_FadeFrame()
|
|
**************************************************************************/
|
|
void
|
|
GFX_FadeStart(
|
|
void
|
|
)
|
|
{
|
|
GFX_GetPalette(tpal1);
|
|
memcpy(tpal2, tpal1, 768);
|
|
}
|
|
|
|
/**************************************************************************
|
|
GFX_FadeFrame () - Fades Individual Frames
|
|
**************************************************************************/
|
|
void
|
|
GFX_FadeFrame(
|
|
char* palette, // INPUT : palette to fade into
|
|
int cur_step, // INPUT : cur step position
|
|
int steps // INPUT : total steps of fade ( 0 - 255 )
|
|
)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 768; i++)
|
|
{
|
|
tpal2[i] = ((palette[i] - tpal1[i]) * cur_step) / steps + tpal1[i];
|
|
}
|
|
|
|
GFX_SetPalette(tpal2, 0);
|
|
}
|
|
|
|
/**************************************************************************
|
|
GFX_SetPalRange() - Sets start and end range for remaping stuff
|
|
**************************************************************************/
|
|
void
|
|
GFX_SetPalRange(
|
|
int start,
|
|
int end
|
|
)
|
|
{
|
|
if (start < end && end < 256 && start >= 0)
|
|
{
|
|
start_lookup = start;
|
|
end_lookup = end;
|
|
}
|
|
}
|
|
|
|
/**************************************************************************
|
|
GFX_GetRGB() - gets R,G and B values from pallete data
|
|
**************************************************************************/
|
|
void
|
|
GFX_GetRGB(
|
|
char *pal, // INPUT : pointer to palette data
|
|
int num, // INPUT : palette entry
|
|
int *red, // OUTPUT: red value
|
|
int *green, // OUTPUT: green value
|
|
int *blue // OUTPUT: blue value
|
|
)
|
|
{
|
|
*red = pal[num * 3 + 0];
|
|
*green = pal[num * 3 + 1];
|
|
*blue = pal[num * 3 + 2];
|
|
}
|
|
|
|
/**************************************************************************
|
|
GFX_Remap() - Finds the closest color avalable
|
|
**************************************************************************/
|
|
int // RETURN: new color number
|
|
GFX_Remap(
|
|
char *pal, // INPUT : pointer to palette data
|
|
int red, // INPUT : red ( 0 - 63 )
|
|
int green, // INPUT : green( 0 - 63 )
|
|
int blue // INPUT : blue ( 0 - 63 )
|
|
)
|
|
{
|
|
int loop, r, g, b, num;
|
|
int low = 769;
|
|
int pos = 0;
|
|
|
|
for (loop = start_lookup; loop < end_lookup + 1; loop++)
|
|
{
|
|
GFX_GetRGB(pal, loop, &r, &g, &b);
|
|
num = abs(r - red) + abs(g - green) + abs(b - blue);
|
|
|
|
if (num <= low)
|
|
{
|
|
low = num;
|
|
pos = loop;
|
|
}
|
|
}
|
|
|
|
return pos;
|
|
}
|
|
|
|
/**************************************************************************
|
|
GFX_MakeLightTable() - make a light/dark palette lookup table
|
|
**************************************************************************/
|
|
void
|
|
GFX_MakeLightTable(
|
|
char *palette, // INPUT : pointer to palette data
|
|
char *ltable, // OUTPUT: pointer to lookup table
|
|
int level // INPUT : - 63 to + 63
|
|
)
|
|
{
|
|
int loop, red, green, blue;
|
|
|
|
for (loop = 0; loop < 256; loop++)
|
|
{
|
|
GFX_GetRGB(palette, loop, &red, &green, &blue);
|
|
|
|
if (red >= 0)
|
|
red += level;
|
|
else
|
|
red = 0;
|
|
|
|
if (green >= 0)
|
|
green += level;
|
|
else
|
|
green = 0;
|
|
|
|
if (blue >= 0)
|
|
blue += level;
|
|
else
|
|
blue = 0;
|
|
|
|
if (level >= 0)
|
|
{
|
|
if (red > 63)
|
|
red = 63;
|
|
if (green > 63)
|
|
green = 63;
|
|
if (blue > 63)
|
|
blue = 63;
|
|
}
|
|
else
|
|
{
|
|
if (red < 0)
|
|
red = 0;
|
|
if (green < 0)
|
|
green = 0;
|
|
if (blue < 0)
|
|
blue = 0;
|
|
}
|
|
|
|
ltable[loop] = GFX_Remap(palette, red, green, blue);
|
|
}
|
|
}
|
|
|
|
/**************************************************************************
|
|
GFX_MakeGreyTable() - make a grey palette lookup table
|
|
**************************************************************************/
|
|
void
|
|
GFX_MakeGreyTable(
|
|
char *palette, // INPUT : pointer to palette data
|
|
char *ltable) // OUTPUT: pointer to lookup table
|
|
{
|
|
int loop, color, red, green, blue;
|
|
|
|
for (loop = 0; loop < 256; loop++)
|
|
{
|
|
GFX_GetRGB(palette, loop, &red, &green, &blue);
|
|
|
|
color = (red + green + blue) / 3;
|
|
|
|
ltable[loop] = GFX_Remap(palette, color, color, color);
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
GFX_GetScreen() - Gets A block of screen memory to CPU memory
|
|
*************************************************************************/
|
|
void
|
|
GFX_GetScreen(
|
|
char *outmem, // OUTPUT: pointer to CPU mem
|
|
int x, // INPUT : x pos
|
|
int y, // INPUT : y pos
|
|
int lx, // INPUT : x length
|
|
int ly // INPUT : y length
|
|
)
|
|
{
|
|
char *source;
|
|
int loop;
|
|
|
|
if (!GFX_ClipLines(&outmem, &x, &y, &lx, &ly))
|
|
return;
|
|
|
|
source = &displaybuffer[ylookup[y] + x];
|
|
|
|
for (loop = 0; loop < ly; loop++)
|
|
{
|
|
memcpy(outmem, source, lx);
|
|
outmem += lx;
|
|
source += SCREENWIDTH;
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
GFX_PutTexture() - Repeats a Picture though the area specified
|
|
*************************************************************************/
|
|
void
|
|
GFX_PutTexture(
|
|
char *intxt, // INPUT : color texture
|
|
int x, // INPUT : x pos
|
|
int y, // INPUT : y pos
|
|
int lx, // INPUT : x length
|
|
int ly // INPUT : y length
|
|
)
|
|
{
|
|
GFX_PIC* h = (GFX_PIC*)intxt;
|
|
int loopy, loopx;
|
|
int maxxloop = lx + abs(x);
|
|
int maxyloop = ly + abs(y);
|
|
int y2 = ly + y - 1;
|
|
int x2 = lx + x - 1;
|
|
int new_ly, ypos, new_lx, xpos;
|
|
char *buf;
|
|
|
|
if (x2 >= SCREENWIDTH)
|
|
x2 = SCREENWIDTH - 1;
|
|
if (y2 >= SCREENHEIGHT)
|
|
y2 = SCREENHEIGHT - 1;
|
|
|
|
for (loopy = y; loopy < maxyloop; loopy += LE_LONG(h->height))
|
|
{
|
|
if (loopy <= y2 && loopy + LE_LONG(h->height) > 0)
|
|
{
|
|
if (loopy < 0)
|
|
{
|
|
new_ly += loopy;
|
|
buf += (-loopy) * LE_LONG(h->width);
|
|
ypos = 0;
|
|
}
|
|
else
|
|
ypos = loopy;
|
|
|
|
for (loopx = x; loopx < maxxloop; loopx += LE_LONG(h->width))
|
|
{
|
|
if (loopx <= x2 && loopx + LE_LONG(h->width) > 0)
|
|
{
|
|
buf = intxt + sizeof(GFX_PIC);
|
|
new_lx = LE_LONG(h->width);
|
|
new_ly = LE_LONG(h->height);
|
|
|
|
if (loopx < 0)
|
|
{
|
|
new_lx += loopx;
|
|
buf += -loopx;
|
|
xpos = 0;
|
|
}
|
|
else
|
|
xpos = loopx;
|
|
|
|
if (xpos + new_lx - 1 >= x2)
|
|
new_lx = (x2 + 1) - xpos;
|
|
|
|
if (ypos + new_ly - 1 >= y2)
|
|
new_ly = (y2 + 1) - ypos;
|
|
|
|
gfx_inmem = buf;
|
|
gfx_xp = xpos;
|
|
gfx_yp = ypos;
|
|
gfx_lx = new_lx;
|
|
gfx_ly = new_ly;
|
|
gfx_imga = LE_LONG(h->width) - new_lx;
|
|
|
|
GFX_PutPic();
|
|
|
|
GFX_MarkUpdate(xpos, ypos, new_lx, new_ly);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
GFX_ShadeArea()- lightens or darkens and area of the screen
|
|
*************************************************************************/
|
|
void
|
|
GFX_ShadeArea(
|
|
int opt, // INPUT : DARK/LIGHT or GREY
|
|
int x, // INPUT : x position
|
|
int y, // INPUT : y position
|
|
int lx, // INPUT : x length
|
|
int ly // INPUT : y length
|
|
)
|
|
{
|
|
int loop;
|
|
char *buf, *cur_table;
|
|
|
|
if (!GFX_ClipLines(NULL, &x, &y, &lx, &ly))
|
|
return;
|
|
|
|
buf = &displaybuffer[x + ylookup[y]];
|
|
|
|
switch (opt)
|
|
{
|
|
case DARK:
|
|
cur_table = dtable;
|
|
break;
|
|
case LIGHT:
|
|
cur_table = ltable;
|
|
break;
|
|
case GREY:
|
|
cur_table = gtable;
|
|
break;
|
|
}
|
|
|
|
GFX_MarkUpdate(x, y, lx, ly);
|
|
|
|
for (loop = 0; loop < ly; loop++)
|
|
{
|
|
GFX_Shade(buf, lx, cur_table);
|
|
buf += SCREENWIDTH;
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
GFX_ShadeShape()- lightens or darkens and area of the screen
|
|
*************************************************************************/
|
|
void
|
|
GFX_ShadeShape(
|
|
int opt, // INPUT : DARK/LIGHT or GREY
|
|
char* inmem, // INPUT : mask 0 = no shade ( GFX format pic )
|
|
int x, // INPUT : x position
|
|
int y // INPUT : y position
|
|
)
|
|
{
|
|
GFX_PIC* h = (GFX_PIC*)inmem;
|
|
GFX_SPRITE* ah;
|
|
char rval;
|
|
char *cur_table;
|
|
char *dest;
|
|
int ox = x;
|
|
int oy = y;
|
|
int lx = LE_LONG(h->width);
|
|
int ly = LE_LONG(h->height);
|
|
|
|
inmem += sizeof(GFX_PIC);
|
|
|
|
rval = GFX_ClipLines(NULL, &ox, &oy, &lx, &ly);
|
|
if (!rval)
|
|
return;
|
|
|
|
switch (opt)
|
|
{
|
|
case DARK:
|
|
cur_table = dtable;
|
|
break;
|
|
|
|
case LIGHT:
|
|
cur_table = ltable;
|
|
break;
|
|
|
|
case GREY:
|
|
cur_table = gtable;
|
|
break;
|
|
}
|
|
|
|
switch (rval)
|
|
{
|
|
case 1:
|
|
dest = displaybuffer + ox + ylookup[oy];
|
|
GFX_ShadeSprite(dest, inmem, cur_table);
|
|
break;
|
|
|
|
case 2:
|
|
ah = (GFX_SPRITE*)inmem;
|
|
while (LE_LONG(ah->offset) != -1)
|
|
{
|
|
inmem += sizeof(GFX_SPRITE);
|
|
ox = LE_LONG(ah->x) + x;
|
|
oy = LE_LONG(ah->y) + y;
|
|
|
|
if (oy > SCREENHEIGHT)
|
|
return;
|
|
|
|
lx = LE_LONG(ah->length);
|
|
ly = 1;
|
|
|
|
if (GFX_ClipLines(NULL, &ox, &oy, &lx, &ly))
|
|
GFX_Shade(&displaybuffer[ox + ylookup[oy]], lx, cur_table);
|
|
|
|
inmem += LE_LONG(ah->length);
|
|
|
|
ah = (GFX_SPRITE*)inmem;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
GFX_VShadeLine () - Shades a vertical line
|
|
*************************************************************************/
|
|
void
|
|
GFX_VShadeLine(
|
|
int opt, // INPUT : DARK/LIGHT or GREY
|
|
int x, // INPUT : x position
|
|
int y, // INPUT : y position
|
|
int ly // INPUT : length of line
|
|
)
|
|
{
|
|
char *cur_table;
|
|
char *outbuf;
|
|
int lx = 1;
|
|
|
|
if (ly < 1)
|
|
return;
|
|
|
|
if (!GFX_ClipLines(NULL, &x, &y, &lx, &ly))
|
|
return;
|
|
|
|
switch (opt)
|
|
{
|
|
case DARK:
|
|
cur_table = dtable;
|
|
break;
|
|
case LIGHT:
|
|
cur_table = ltable;
|
|
break;
|
|
case GREY:
|
|
cur_table = gtable;
|
|
break;
|
|
}
|
|
|
|
GFX_MarkUpdate(x, y, lx, ly);
|
|
|
|
outbuf = &displaybuffer[x + ylookup[y]];
|
|
|
|
while (ly--)
|
|
{
|
|
*outbuf = cur_table[(uint8_t)*outbuf];
|
|
outbuf += SCREENWIDTH;
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
GFX_HShadeLine () Shades a Horizontal Line
|
|
*************************************************************************/
|
|
void
|
|
GFX_HShadeLine(
|
|
int opt, // INPUT : DARK/LIGHT or GREY
|
|
int x, // INPUT : x position
|
|
int y, // INPUT : y position
|
|
int lx // INPUT : length of line
|
|
)
|
|
{
|
|
char *cur_table;
|
|
char *outbuf;
|
|
int ly = 1;
|
|
|
|
if (lx < 1)
|
|
return;
|
|
|
|
if (!GFX_ClipLines(NULL, &x, &y, &lx, &ly))
|
|
return;
|
|
|
|
switch (opt)
|
|
{
|
|
case DARK:
|
|
cur_table = dtable;
|
|
break;
|
|
case LIGHT:
|
|
cur_table = ltable;
|
|
break;
|
|
case GREY:
|
|
cur_table = gtable;
|
|
break;
|
|
}
|
|
|
|
GFX_MarkUpdate(x, y, lx, ly);
|
|
|
|
outbuf = &displaybuffer[x + ylookup[y]];
|
|
|
|
GFX_Shade(outbuf, lx, cur_table);
|
|
}
|
|
|
|
/*************************************************************************
|
|
GFX_LightBox()- Draws a rectangle border with light source
|
|
*************************************************************************/
|
|
void
|
|
GFX_LightBox(
|
|
int opt, // INPUT : light source
|
|
int x, // INPUT : x position
|
|
int y, // INPUT : y position
|
|
int lx, // INPUT : x length
|
|
int ly // INPUT : y length
|
|
)
|
|
{
|
|
if (lx < 1 || ly < 1)
|
|
return;
|
|
|
|
switch (opt)
|
|
{
|
|
case UPPER_LEFT:
|
|
GFX_HShadeLine(LIGHT, x, y, lx - 1);
|
|
GFX_VShadeLine(LIGHT, x, y + 1, ly - 2);
|
|
GFX_HShadeLine(DARK, x, y + ly - 1, lx);
|
|
GFX_VShadeLine(DARK, x + lx - 1, y + 1, ly - 2);
|
|
break;
|
|
|
|
case UPPER_RIGHT:
|
|
default:
|
|
GFX_HShadeLine(LIGHT, x + 1, y, lx - 1);
|
|
GFX_VShadeLine(LIGHT, x + lx - 1, y + 1, ly - 2);
|
|
GFX_HShadeLine(DARK, x, y + ly - 1, lx);
|
|
GFX_VShadeLine(DARK, x, y, ly - 1);
|
|
break;
|
|
|
|
case LOWER_LEFT:
|
|
GFX_HShadeLine(LIGHT, x, y + ly - 1, lx - 1);
|
|
GFX_VShadeLine(LIGHT, x, y + 1, ly - 2);
|
|
GFX_HShadeLine(DARK, x, y, lx);
|
|
GFX_VShadeLine(DARK, x + lx - 1, y + 1, ly - 1);
|
|
break;
|
|
|
|
case LOWER_RIGHT:
|
|
GFX_HShadeLine(LIGHT, x + 1, y, lx - 1);
|
|
GFX_VShadeLine(LIGHT, x + lx - 1, y + 1, ly - 2);
|
|
GFX_HShadeLine(DARK, x, y, lx);
|
|
GFX_VShadeLine(DARK, x, y + 1, ly - 2);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
GFX_ColorBox () - sets a rectangular area to color
|
|
*************************************************************************/
|
|
void
|
|
GFX_ColorBox(
|
|
int x, // INPUT : x position
|
|
int y, // INPUT : y position
|
|
int lx, // INPUT : width
|
|
int ly, // INPUT : length
|
|
int color // INPUT : fill color ( 0 - 255 )
|
|
)
|
|
{
|
|
|
|
char *outbuf;
|
|
|
|
if (lx < 1 || ly < 1)
|
|
return;
|
|
|
|
if (!GFX_ClipLines(NULL, &x, &y, &lx, &ly))
|
|
return;
|
|
|
|
outbuf = &displaybuffer[x + ylookup[y]];
|
|
|
|
GFX_MarkUpdate(x, y, lx, ly);
|
|
|
|
if (color < 0)
|
|
{
|
|
while (ly--)
|
|
{
|
|
GFX_HLine(x, y, lx, color);
|
|
y++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (ly--)
|
|
{
|
|
memset(outbuf, color, lx);
|
|
outbuf += SCREENWIDTH;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
GFX_HLine () - plots a horizontal line in color
|
|
*************************************************************************/
|
|
void
|
|
GFX_HLine(
|
|
int x, // INPUT : x position
|
|
int y, // INPUT : y position
|
|
int lx, // INPUT : width
|
|
int color // INPUT : fill color ( 0 - 255 )
|
|
)
|
|
{
|
|
char *outbuf;
|
|
int loop;
|
|
int ly = 1;
|
|
|
|
if (lx < 1)
|
|
return;
|
|
|
|
if (!GFX_ClipLines(0, &x, &y, &lx, &ly))
|
|
return;
|
|
|
|
outbuf = &displaybuffer[x + ylookup[y]];
|
|
|
|
GFX_MarkUpdate(x, y, lx, 1);
|
|
|
|
if (color < 0)
|
|
{
|
|
for (loop = 0; loop < lx; loop++)
|
|
{
|
|
*outbuf ^= (color + 255);
|
|
outbuf++;
|
|
}
|
|
}
|
|
else
|
|
memset(outbuf, color, lx);
|
|
}
|
|
|
|
/*************************************************************************
|
|
GFX_VLine () plots a vertical line in color
|
|
*************************************************************************/
|
|
void
|
|
GFX_VLine(
|
|
int x, // INPUT : x position
|
|
int y, // INPUT : y position
|
|
int ly, // INPUT : length
|
|
int color // INPUT : fill color ( 0 - 255 )
|
|
)
|
|
{
|
|
char *outbuf;
|
|
int lx = 1;
|
|
|
|
if (ly < 1)
|
|
return;
|
|
|
|
if (!GFX_ClipLines(0, &x, &y, &lx, &ly))
|
|
return;
|
|
|
|
outbuf = &displaybuffer[x + ylookup[y]];
|
|
|
|
GFX_MarkUpdate(x, y, 1, ly);
|
|
|
|
if (color < 0)
|
|
{
|
|
while (ly--)
|
|
{
|
|
*outbuf ^= (color + 255);
|
|
outbuf += SCREENWIDTH;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (ly--)
|
|
{
|
|
*outbuf = color;
|
|
outbuf += SCREENWIDTH;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
GFX_Line () plots a line in color ( Does no Clipping )
|
|
*************************************************************************/
|
|
void
|
|
GFX_Line(
|
|
int x, // INPUT : x start point
|
|
int y, // INPUT : y start point
|
|
int x2, // INPUT : x2 end point
|
|
int y2, // INPUT : y2 end point
|
|
int color // INPUT : color ( 0 - 255 )
|
|
)
|
|
{
|
|
int addx = 1;
|
|
int addy = 1;
|
|
int dely = y2 - y;
|
|
int delx = x2 - x;
|
|
int err, maxloop;
|
|
|
|
if (delx < 0)
|
|
{
|
|
delx = -delx;
|
|
addx = -addx;
|
|
}
|
|
if (dely < 0)
|
|
{
|
|
dely = -dely;
|
|
addy = -addy;
|
|
}
|
|
|
|
if (delx >= dely)
|
|
{
|
|
err = -(dely >> 1);
|
|
maxloop = delx + 1;
|
|
}
|
|
else
|
|
{
|
|
err = (delx >> 1);
|
|
maxloop = dely + 1;
|
|
}
|
|
|
|
if (delx >= dely)
|
|
{
|
|
while (maxloop)
|
|
{
|
|
if (x >= 0 && x < 320 && y >= 0 && y < 200)
|
|
{
|
|
displaybuffer[x + ylookup[y]] = color;
|
|
}
|
|
maxloop--;
|
|
err += dely;
|
|
x += addx;
|
|
|
|
if (err > 0)
|
|
{
|
|
err -= delx;
|
|
y += addy;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (maxloop)
|
|
{
|
|
if (x >= 0 && x <= 320 && y >= 0 && y < 200)
|
|
{
|
|
displaybuffer[x + ylookup[y]] = color;
|
|
}
|
|
maxloop--;
|
|
err += delx;
|
|
y += addy;
|
|
|
|
if (err > 0)
|
|
{
|
|
err -= dely;
|
|
x += addx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
GFX_Rectangle () - sets a rectangular border to color
|
|
*************************************************************************/
|
|
void
|
|
GFX_Rectangle(
|
|
int x, // INPUT : x position
|
|
int y, // INPUT : y position
|
|
int lx, // INPUT : width
|
|
int ly, // INPUT : length
|
|
int color // INPUT : fill color ( 0 - 255 )
|
|
)
|
|
{
|
|
if (ly < 1 || lx < 1)
|
|
return;
|
|
|
|
GFX_HLine(x, y, lx, color);
|
|
GFX_HLine(x, y + ly - 1, lx, color);
|
|
GFX_VLine(x, y + 1, ly - 2, color);
|
|
GFX_VLine(x + lx - 1, y + 1, ly - 2, color);
|
|
}
|
|
|
|
/*************************************************************************
|
|
GFX_ScalePic () - Scales picture optionaly make color 0 see thru
|
|
*************************************************************************/
|
|
void
|
|
GFX_ScalePic(
|
|
char *buffin, // INPUT : pointer to pic data
|
|
int x, // INPUT : x display position
|
|
int y, // INPUT : y display position
|
|
int new_lx, // INPUT : new x length
|
|
int new_ly, // INPUT : new y length
|
|
int see_thru // INPUT : TRUE = see thru
|
|
)
|
|
{
|
|
GFX_PIC* h = (GFX_PIC*)buffin;
|
|
char *dest = displaybuffer;
|
|
int accum_x, accum_y, i;
|
|
char *pic = buffin + sizeof(GFX_PIC);
|
|
int addx = (LE_LONG(h->width)<<16) / new_lx;
|
|
int addy = (LE_LONG(h->height)<<16) / new_ly;
|
|
accum_x = 0;
|
|
accum_y = 0;
|
|
|
|
if (h->type == GSPRITE)
|
|
{
|
|
GFX_PutSprite(buffin, x, y);
|
|
return;
|
|
}
|
|
|
|
if (x < 0)
|
|
{
|
|
accum_x = addx * (-x);
|
|
pic += accum_x >> 16;
|
|
accum_x &= 0xffff;
|
|
new_lx += x;
|
|
x = 0;
|
|
}
|
|
|
|
if (y < 0)
|
|
{
|
|
accum_y = addy * (-y);
|
|
pic += (LE_LONG(h->width)) * (accum_y >> 16);
|
|
accum_y &= 0xffff;
|
|
new_ly += y;
|
|
y = 0;
|
|
}
|
|
|
|
if (x + new_lx > SCREENWIDTH)
|
|
{
|
|
new_lx = SCREENWIDTH - x;
|
|
}
|
|
if (y + new_ly > SCREENHEIGHT)
|
|
{
|
|
new_ly = SCREENHEIGHT - y;
|
|
}
|
|
|
|
dest = &displaybuffer[x + ylookup[y]];
|
|
|
|
GFX_MarkUpdate(x, y, new_lx, new_ly);
|
|
|
|
tablelen = new_lx;
|
|
|
|
for (i = new_lx - 1; i >= 0; i--)
|
|
{
|
|
stable[i] = (accum_x >> 16);
|
|
accum_x += addx;
|
|
}
|
|
|
|
if (see_thru)
|
|
{
|
|
while (new_ly--)
|
|
{
|
|
GFX_CScaleLine(dest, pic + LE_LONG(h->width) * (accum_y>>16));
|
|
accum_y += addy;
|
|
dest += SCREENWIDTH;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (new_ly--)
|
|
{
|
|
GFX_ScaleLine(dest, pic + LE_LONG(h->width) * (accum_y>>16));
|
|
accum_y += addy;
|
|
dest += SCREENWIDTH;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
GFX_MarkUpdate () Marks an area to be draw with GFX_DrawScreen()
|
|
*************************************************************************/
|
|
void
|
|
GFX_MarkUpdate(
|
|
int x, // INPUT : x position
|
|
int y, // INPUT : y position
|
|
int lx, // INPUT : x length
|
|
int ly // INPUT : y length
|
|
)
|
|
{
|
|
int x2 = x + lx - 1;
|
|
int y2 = y + ly - 1;
|
|
int ud_x2 = ud_x + ud_lx - 1;
|
|
int ud_y2 = ud_y + ud_ly - 1;
|
|
|
|
if (update_start)
|
|
{
|
|
if (x < ud_x)
|
|
ud_x = x;
|
|
|
|
if (y < ud_y)
|
|
ud_y = y;
|
|
|
|
if (x2 > ud_x2)
|
|
ud_x2 = x2;
|
|
if (y2 > ud_y2)
|
|
ud_y2 = y2;
|
|
}
|
|
else
|
|
{
|
|
ud_x = x;
|
|
ud_y = y;
|
|
ud_x2 = x2;
|
|
ud_y2 = y2;
|
|
if (lx + ly > 0)
|
|
update_start = 1;
|
|
}
|
|
if ((ud_x) & 3)
|
|
ud_x = ud_x - (ud_x & 3);
|
|
|
|
if (ud_x < 0)
|
|
ud_x = 0;
|
|
|
|
if (ud_y < 0)
|
|
ud_y = 0;
|
|
|
|
ud_lx = (ud_x2 - ud_x + 1);
|
|
ud_ly = (ud_y2 - ud_y + 1);
|
|
|
|
if ((ud_lx) & 3)
|
|
ud_lx += 4 - (ud_lx & 3);
|
|
|
|
if (ud_x + ud_lx > SCREENWIDTH)
|
|
ud_lx = SCREENWIDTH - ud_x;
|
|
if (ud_y + ud_ly > SCREENHEIGHT)
|
|
ud_ly = SCREENHEIGHT - ud_y;
|
|
}
|
|
|
|
/*************************************************************************
|
|
GFX_ForceUpdate () Marks an area to be draw with GFX_DrawScreen()
|
|
*************************************************************************/
|
|
void
|
|
GFX_ForceUpdate(
|
|
int x, // INPUT : x position
|
|
int y, // INPUT : y position
|
|
int lx, // INPUT : x length
|
|
int ly // INPUT : y length
|
|
)
|
|
{
|
|
ud_x = x;
|
|
ud_y = y;
|
|
ud_lx = lx;
|
|
ud_ly = ly;
|
|
o_ud_x = x;
|
|
o_ud_y = y;
|
|
o_ud_lx = lx;
|
|
o_ud_ly = ly;
|
|
}
|
|
|
|
/***************************************************************************
|
|
GFX_SetFrameHook () sets function to call before every screen update
|
|
***************************************************************************/
|
|
void
|
|
GFX_SetFrameHook(
|
|
void (*func)(void (*)(void)) // INPUT : pointer to function
|
|
)
|
|
{
|
|
framehook = func;
|
|
}
|
|
|
|
/***************************************************************************
|
|
GFX_WaitUpdate () - Updates screen at specified frame rate
|
|
***************************************************************************/
|
|
void
|
|
GFX_WaitUpdate(
|
|
int count // INPUT : frame rate ( MAX = 70 )
|
|
)
|
|
{
|
|
static int now;
|
|
int get_count, loop;
|
|
|
|
if (count > 70)
|
|
count = 70;
|
|
else if (count < 1)
|
|
count = 70;
|
|
|
|
get_count = 70 / count;
|
|
|
|
GFX_MarkUpdate(o_ud_x, o_ud_y, o_ud_lx, o_ud_ly);
|
|
|
|
for (loop = 0; loop < get_count; loop++)
|
|
{
|
|
while (now == GFX_GetFrameCount())
|
|
{
|
|
}
|
|
now = GFX_GetFrameCount();
|
|
}
|
|
|
|
if (update_start)
|
|
{
|
|
if (framehook)
|
|
framehook(GFX_DisplayScreen);
|
|
else
|
|
GFX_DisplayScreen();
|
|
}
|
|
|
|
o_ud_x = ud_x;
|
|
o_ud_y = ud_y;
|
|
o_ud_lx = ud_lx;
|
|
o_ud_ly = ud_ly;
|
|
|
|
I_FinishUpdate();
|
|
}
|
|
|
|
/***************************************************************************
|
|
GFX_DisplayUpdate () - Copys Marked areas to display
|
|
***************************************************************************/
|
|
void
|
|
GFX_DisplayUpdate(
|
|
void
|
|
)
|
|
{
|
|
static int hold;
|
|
|
|
I_GetEvent();
|
|
GFX_UpdateTimer();
|
|
|
|
while (hold == framecount)
|
|
{
|
|
GFX_UpdateTimer();
|
|
}
|
|
|
|
GFX_MarkUpdate(o_ud_x, o_ud_y, o_ud_lx, o_ud_ly);
|
|
|
|
if (update_start)
|
|
{
|
|
if (framehook)
|
|
framehook(GFX_DisplayScreen);
|
|
else
|
|
GFX_DisplayScreen();
|
|
}
|
|
|
|
o_ud_x = ud_x;
|
|
o_ud_y = ud_y;
|
|
o_ud_lx = ud_lx;
|
|
o_ud_ly = ud_ly;
|
|
|
|
hold = framecount;
|
|
|
|
I_FinishUpdate();
|
|
}
|
|
|
|
/***************************************************************************
|
|
GFX_PutImage() - places image in displaybuffer and performs cliping
|
|
***************************************************************************/
|
|
void
|
|
GFX_PutImage(
|
|
char *image, // INPUT : image data
|
|
int x, // INPUT : x position
|
|
int y, // INPUT : y position
|
|
int see_thru // INPUT : true = masked, false = put block
|
|
)
|
|
{
|
|
GFX_PIC* h = (GFX_PIC*)image;
|
|
|
|
gfx_lx = LE_LONG(h->width);
|
|
gfx_ly = LE_LONG(h->height);
|
|
|
|
if (h->type == GSPRITE)
|
|
{
|
|
GFX_PutSprite(image, x, y);
|
|
}
|
|
else
|
|
{
|
|
image += sizeof(GFX_PIC);
|
|
|
|
if (GFX_ClipLines(&image, &x, &y, &gfx_lx, &gfx_ly))
|
|
{
|
|
GFX_MarkUpdate(x, y, gfx_lx, gfx_ly);
|
|
|
|
gfx_xp = x;
|
|
gfx_yp = y;
|
|
|
|
gfx_inmem = image;
|
|
gfx_imga = LE_LONG(h->width);
|
|
|
|
if (!see_thru)
|
|
{
|
|
gfx_imga -= gfx_lx;
|
|
GFX_PutPic();
|
|
}
|
|
else
|
|
GFX_PutMaskPic();
|
|
}
|
|
}
|
|
}
|
|
|
|
/***************************************************************************
|
|
GFX_PutSprite () -Puts a Sprite into display buffer
|
|
***************************************************************************/
|
|
void
|
|
GFX_PutSprite(
|
|
char *inmem, // INPUT : inmem
|
|
int x, // INPUT : x pos
|
|
int y // INPUT : y pos
|
|
)
|
|
{
|
|
GFX_PIC *h = (GFX_PIC*)inmem;
|
|
GFX_SPRITE *ah;
|
|
char rval;
|
|
char* dest;
|
|
char *outline;
|
|
int ox = x;
|
|
int oy = y;
|
|
int lx = LE_LONG(h->width);
|
|
int ly = LE_LONG(h->height);
|
|
|
|
rval = GFX_ClipLines(NULL, &ox, &oy, &lx, &ly);
|
|
|
|
if (!rval)
|
|
return;
|
|
|
|
inmem += sizeof(GFX_PIC);
|
|
|
|
switch (rval)
|
|
{
|
|
default:
|
|
break;
|
|
|
|
case 1:
|
|
dest = displaybuffer + ox + ylookup[oy];
|
|
GFX_DrawSprite(dest, inmem);
|
|
break;
|
|
|
|
case 2:
|
|
ah = (GFX_SPRITE*)inmem;
|
|
|
|
while (LE_LONG(ah->offset) != -1)
|
|
{
|
|
inmem += sizeof(GFX_SPRITE);
|
|
|
|
ox = LE_LONG(ah->x) + x;
|
|
oy = LE_LONG(ah->y) + y;
|
|
|
|
if (oy > SCREENHEIGHT) break;
|
|
|
|
lx = LE_LONG(ah->length);
|
|
ly = 1;
|
|
|
|
outline = inmem;
|
|
|
|
if (GFX_ClipLines(&outline, &ox, &oy, &lx, &ly))
|
|
memcpy(displaybuffer + ox + ylookup[oy], outline, lx);
|
|
|
|
inmem += LE_LONG(ah->length);
|
|
|
|
ah = (GFX_SPRITE*)inmem;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/***************************************************************************
|
|
GFX_OverlayImage() - places image in displaybuffer and performs cliping
|
|
***************************************************************************/
|
|
void
|
|
GFX_OverlayImage(
|
|
char *baseimage, // INPUT : base image data
|
|
char *overimage, // INPUT : overlay image data
|
|
int x, // INPUT : x position
|
|
int y // INPUT : y position
|
|
)
|
|
{
|
|
GFX_PIC* bh = (GFX_PIC*)baseimage;
|
|
GFX_PIC* oh = (GFX_PIC*)overimage;
|
|
int addnum, loop, i;
|
|
int x2 = x + LE_LONG(oh->width) - 1;
|
|
int y2 = y + LE_LONG(oh->height) - 1;
|
|
|
|
if (x >= 0 && y >= 0 && x2 < LE_LONG(bh->width) && y2 < LE_LONG(bh->height))
|
|
{
|
|
baseimage += sizeof(GFX_PIC);
|
|
baseimage += (x + (y * LE_LONG(bh->width)));
|
|
|
|
overimage += sizeof(GFX_PIC);
|
|
|
|
addnum = LE_LONG(bh->width) - LE_LONG(oh->width);
|
|
|
|
for (loop = 0; loop < LE_LONG(oh->height); loop++)
|
|
{
|
|
for (i = 0; i < LE_LONG(oh->width); i++, baseimage++, overimage++)
|
|
{
|
|
if (i != 255)
|
|
*baseimage = *overimage;
|
|
}
|
|
baseimage += addnum;
|
|
}
|
|
}
|
|
}
|
|
|
|
/***************************************************************************
|
|
GFX_StrPixelLen() - Calculates the length of a GFX string
|
|
***************************************************************************/
|
|
int // RETURNS : pixel length
|
|
GFX_StrPixelLen(
|
|
FONT *infont, // INPUT : pointer to current font
|
|
char *instr, // INPUT : pointer to string
|
|
int maxloop // INPUT : length of string
|
|
)
|
|
{
|
|
int loop;
|
|
int outlen = 0;
|
|
|
|
for (loop = 0; loop < maxloop; loop++)
|
|
{
|
|
outlen += infont->width[instr[loop]] + fontspacing;
|
|
}
|
|
|
|
return outlen;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
GFX_PutChar () - Draws charater to displaybuffer and clips
|
|
--------------------------------------------------------------------------*/
|
|
int
|
|
GFX_PutChar(
|
|
int x, // INPUT : x position
|
|
int y, // INPUT : y position
|
|
unsigned char inchar, // INPUT : char to print
|
|
FONT* font, // INPUT : pointer to font
|
|
int basecolor // INPUT : font base color
|
|
)
|
|
{
|
|
char* source = (char*)font + sizeof(FONT);
|
|
char *dest;
|
|
int lx = font->width[inchar];
|
|
int addx;
|
|
int ly = LE_LONG(font->height);
|
|
char* cdata = source + LE_SHORT(font->charofs[inchar]);
|
|
addx = lx;
|
|
|
|
if (GFX_ClipLines(&cdata, &x, &y, &lx, &ly))
|
|
{
|
|
dest = displaybuffer + x + ylookup[y];
|
|
|
|
GFX_MarkUpdate(x, y, lx, ly);
|
|
|
|
addx = addx - lx;
|
|
|
|
GFX_DrawChar(dest, cdata, lx, ly, addx, basecolor);
|
|
|
|
return lx;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/***************************************************************************
|
|
GFX_Print () - prints a string using specified font with basecolor
|
|
***************************************************************************/
|
|
int // RETURN: length of print
|
|
GFX_Print(
|
|
int x, // INPUT : x position
|
|
int y, // INPUT : y position
|
|
char *str, // INPUT : string to print
|
|
FONT* infont, // INPUT : pointer to font
|
|
int basecolor // INPUT : basecolor of font
|
|
)
|
|
{
|
|
FONT* font = infont;
|
|
int lx = 0;
|
|
int cwidth;
|
|
unsigned char ch;
|
|
|
|
basecolor--;
|
|
|
|
if (strlen(str))
|
|
{
|
|
while ((ch = *str++) != 0)
|
|
{
|
|
if (LE_SHORT(font->charofs[ch]) == (short)-1)
|
|
continue;
|
|
cwidth = GFX_PutChar(x, y, ch, font, basecolor);
|
|
lx += (cwidth + fontspacing);
|
|
x += (font->width[ch] + fontspacing);
|
|
}
|
|
}
|
|
|
|
return lx;
|
|
}
|
|
|
|
/***************************************************************************
|
|
GFX_3D_SetView() Sets user view in 3d space
|
|
***************************************************************************/
|
|
void
|
|
GFX_3D_SetView(
|
|
int x, // INPUT : x position
|
|
int y, // INPUT : y position
|
|
int z // INPUT : z position
|
|
)
|
|
{
|
|
G3D_viewx = x;
|
|
G3D_viewy = y;
|
|
G3D_viewz = z;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
GFX_3DPoint () plots a points in 3D space
|
|
--------------------------------------------------------------------------*/
|
|
void
|
|
GFX_3DPoint(
|
|
void
|
|
)
|
|
{
|
|
G3D_x -= G3D_viewx;
|
|
G3D_y -= G3D_viewy;
|
|
G3D_z -= G3D_viewz;
|
|
|
|
G3D_screenx = ((G3D_x * (G3D_DIST<<11)) / G3D_z) >> 11;
|
|
G3D_screeny = ((G3D_y * (G3D_DIST<<11)) / G3D_z) >> 11;
|
|
|
|
G3D_screenx += G3D_viewx;
|
|
G3D_screeny += G3D_viewy;
|
|
}
|
|
|
|
/***************************************************************************
|
|
GFX_3D_PutImage() - places image in displaybuffer and performs cliping
|
|
***************************************************************************/
|
|
void
|
|
GFX_3D_PutImage(
|
|
char *image, // INPUT : image data
|
|
int x, // INPUT : x position
|
|
int y, // INPUT : y position
|
|
int z, // INPUT : z position ( distance )
|
|
int see_thru // INPUT : true = masked, false = put block
|
|
)
|
|
{
|
|
GFX_PIC* h = (GFX_PIC*)image;
|
|
int x1, y1, new_lx, new_ly;
|
|
|
|
if (z == G3D_DIST)
|
|
{
|
|
GFX_MarkUpdate(x, y, LE_LONG(h->width), LE_LONG(h->height));
|
|
GFX_PutImage(image, x, y, see_thru);
|
|
}
|
|
else
|
|
{
|
|
G3D_x = x;
|
|
G3D_y = y;
|
|
G3D_z = z;
|
|
GFX_3DPoint();
|
|
x1 = G3D_screenx;
|
|
y1 = G3D_screeny;
|
|
|
|
G3D_x = x + LE_LONG(h->width) - 1;
|
|
G3D_y = y + LE_LONG(h->height) - 1;
|
|
G3D_z = z;
|
|
GFX_3DPoint();
|
|
|
|
new_lx = G3D_screenx - x1;
|
|
new_ly = G3D_screeny - y1;
|
|
|
|
GFX_MarkUpdate(x1, y1, new_lx, new_ly);
|
|
GFX_ScalePic(image, x1, y1, new_lx, new_ly, see_thru);
|
|
}
|
|
}
|
|
|