Added Uq-Ruan Masters game - it compiles but does not work (renders too slowly? Another problem?)
This commit is contained in:
639
project/jni/application/sc2/src/libs/graphics/cmap.c
Normal file
639
project/jni/application/sc2/src/libs/graphics/cmap.c
Normal file
@@ -0,0 +1,639 @@
|
||||
//Copyright Paul Reiche, Fred Ford. 1992-2002
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "libs/graphics/cmap.h"
|
||||
#include "libs/threadlib.h"
|
||||
#include "libs/timelib.h"
|
||||
#include "libs/inplib.h"
|
||||
#include "libs/strlib.h"
|
||||
// for GetStringAddress()
|
||||
#include "libs/log.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
typedef struct xform_control
|
||||
{
|
||||
int CMapIndex; // -1 means unused
|
||||
COLORMAPPTR CMapPtr;
|
||||
SIZE Ticks;
|
||||
DWORD StartTime;
|
||||
DWORD EndTime;
|
||||
Color OldCMap[NUMBER_OF_PLUTVALS];
|
||||
} XFORM_CONTROL;
|
||||
|
||||
#define MAX_XFORMS 16
|
||||
static struct
|
||||
{
|
||||
XFORM_CONTROL TaskControl[MAX_XFORMS];
|
||||
volatile int Highest;
|
||||
// 'pending' is Highest >= 0
|
||||
Mutex Lock;
|
||||
} XFormControl;
|
||||
|
||||
static int fadeAmount = FADE_NORMAL_INTENSITY;
|
||||
static int fadeDelta;
|
||||
static TimeCount fadeStartTime;
|
||||
static sint32 fadeInterval;
|
||||
|
||||
#define SPARE_COLORMAPS 20
|
||||
|
||||
// Colormaps are rapidly replaced in some parts of the game, so
|
||||
// it pays to have some spares on hand
|
||||
static TFB_ColorMap *poolhead;
|
||||
static int poolcount;
|
||||
|
||||
static TFB_ColorMap * colormaps[MAX_COLORMAPS];
|
||||
static int mapcount;
|
||||
Mutex maplock;
|
||||
|
||||
|
||||
void
|
||||
InitColorMaps (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
// init colormaps
|
||||
maplock = CreateMutex ("Colormaps Lock", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
|
||||
|
||||
// init xform control
|
||||
XFormControl.Highest = -1;
|
||||
XFormControl.Lock = CreateMutex ("Transform Lock", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
|
||||
for (i = 0; i < MAX_XFORMS; ++i)
|
||||
XFormControl.TaskControl[i].CMapIndex = -1;
|
||||
}
|
||||
|
||||
void
|
||||
UninitColorMaps (void)
|
||||
{
|
||||
TFB_ColorMap *next;
|
||||
|
||||
// free spares
|
||||
for ( ; poolhead; poolhead = next)
|
||||
{
|
||||
next = poolhead->next;
|
||||
HFree (poolhead);
|
||||
}
|
||||
|
||||
// uninit xform control
|
||||
DestroyMutex (XFormControl.Lock);
|
||||
|
||||
// uninit colormaps
|
||||
DestroyMutex (maplock);
|
||||
}
|
||||
|
||||
static inline TFB_ColorMap *
|
||||
alloc_colormap (void)
|
||||
// returns an addrefed object
|
||||
{
|
||||
TFB_ColorMap *map;
|
||||
|
||||
if (poolhead)
|
||||
{ // have some spares
|
||||
map = poolhead;
|
||||
poolhead = map->next;
|
||||
--poolcount;
|
||||
}
|
||||
else
|
||||
{ // no spares, need a new one
|
||||
map = HMalloc (sizeof (*map));
|
||||
map->palette = AllocNativePalette ();
|
||||
if (!map->palette)
|
||||
{
|
||||
HFree (map);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
map->next = NULL;
|
||||
map->index = -1;
|
||||
map->refcount = 1;
|
||||
map->version = 0;
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
static TFB_ColorMap *
|
||||
clone_colormap (TFB_ColorMap *from, int index)
|
||||
// returns an addrefed object
|
||||
{
|
||||
TFB_ColorMap *map;
|
||||
|
||||
map = alloc_colormap ();
|
||||
if (!map)
|
||||
{
|
||||
log_add (log_Warning, "FATAL: clone_colormap(): "
|
||||
"could not allocate a map");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
{ // fresh new map
|
||||
map->index = index;
|
||||
if (from)
|
||||
map->version = from->version;
|
||||
}
|
||||
map->version++;
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
static inline void
|
||||
free_colormap (TFB_ColorMap *map)
|
||||
{
|
||||
if (!map)
|
||||
{
|
||||
log_add (log_Warning, "free_colormap(): tried to free a NULL map");
|
||||
return;
|
||||
}
|
||||
|
||||
if (poolcount < SPARE_COLORMAPS)
|
||||
{ // return to the spare pool
|
||||
map->next = poolhead;
|
||||
poolhead = map;
|
||||
++poolcount;
|
||||
}
|
||||
else
|
||||
{ // don't need any more spares
|
||||
FreeNativePalette (map->palette);
|
||||
HFree (map);
|
||||
}
|
||||
}
|
||||
|
||||
static inline TFB_ColorMap *
|
||||
get_colormap (int index)
|
||||
{
|
||||
TFB_ColorMap *map;
|
||||
|
||||
map = colormaps[index];
|
||||
if (!map)
|
||||
{
|
||||
log_add (log_Fatal, "BUG: get_colormap(): map not present");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
map->refcount++;
|
||||
return map;
|
||||
}
|
||||
|
||||
static inline void
|
||||
release_colormap (TFB_ColorMap *map)
|
||||
{
|
||||
if (!map)
|
||||
return;
|
||||
|
||||
if (map->refcount <= 0)
|
||||
{
|
||||
log_add (log_Warning, "BUG: release_colormap(): refcount not >0");
|
||||
return;
|
||||
}
|
||||
|
||||
map->refcount--;
|
||||
if (map->refcount == 0)
|
||||
free_colormap (map);
|
||||
}
|
||||
|
||||
void
|
||||
TFB_ReturnColorMap (TFB_ColorMap *map)
|
||||
{
|
||||
LockMutex (maplock);
|
||||
release_colormap (map);
|
||||
UnlockMutex (maplock);
|
||||
}
|
||||
|
||||
TFB_ColorMap *
|
||||
TFB_GetColorMap (int index)
|
||||
{
|
||||
TFB_ColorMap *map;
|
||||
|
||||
LockMutex (maplock);
|
||||
map = get_colormap (index);
|
||||
UnlockMutex (maplock);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
void
|
||||
GetColorMapColors (Color *colors, TFB_ColorMap *map)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!map)
|
||||
return;
|
||||
|
||||
for (i = 0; i < NUMBER_OF_PLUTVALS; ++i)
|
||||
colors[i] = GetNativePaletteColor (map->palette, i);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
SetColorMap (COLORMAPPTR map)
|
||||
{
|
||||
int start, end;
|
||||
int total_size;
|
||||
UBYTE *colors = (UBYTE*)map;
|
||||
TFB_ColorMap **mpp;
|
||||
|
||||
if (!map)
|
||||
return TRUE;
|
||||
|
||||
start = *colors++;
|
||||
end = *colors++;
|
||||
if (start > end)
|
||||
{
|
||||
log_add (log_Warning, "ERROR: SetColorMap(): "
|
||||
"starting map (%d) not less or eq ending (%d)",
|
||||
start, end);
|
||||
return FALSE;
|
||||
}
|
||||
if (start >= MAX_COLORMAPS)
|
||||
{
|
||||
log_add (log_Warning, "ERROR: SetColorMap(): "
|
||||
"starting map (%d) beyond range (0-%d)",
|
||||
start, (int)MAX_COLORMAPS - 1);
|
||||
return FALSE;
|
||||
}
|
||||
if (end >= MAX_COLORMAPS)
|
||||
{
|
||||
log_add (log_Warning, "SetColorMap(): "
|
||||
"ending map (%d) beyond range (0-%d)\n",
|
||||
end, (int)MAX_COLORMAPS - 1);
|
||||
end = MAX_COLORMAPS - 1;
|
||||
}
|
||||
|
||||
total_size = end + 1;
|
||||
|
||||
LockMutex (maplock);
|
||||
|
||||
if (total_size > mapcount)
|
||||
mapcount = total_size;
|
||||
|
||||
// parse the supplied PLUTs into our colormaps
|
||||
for (mpp = colormaps + start; start <= end; ++start, ++mpp)
|
||||
{
|
||||
int i;
|
||||
TFB_ColorMap *newmap;
|
||||
TFB_ColorMap *oldmap;
|
||||
|
||||
oldmap = *mpp;
|
||||
newmap = clone_colormap (oldmap, start);
|
||||
|
||||
for (i = 0; i < NUMBER_OF_PLUTVALS; ++i, colors += PLUTVAL_BYTE_SIZE)
|
||||
{
|
||||
Color color;
|
||||
|
||||
color.a = 0xff;
|
||||
color.r = colors[PLUTVAL_RED];
|
||||
color.g = colors[PLUTVAL_GREEN];
|
||||
color.b = colors[PLUTVAL_BLUE];
|
||||
SetNativePaletteColor (newmap->palette, i, color);
|
||||
}
|
||||
|
||||
*mpp = newmap;
|
||||
release_colormap (oldmap);
|
||||
}
|
||||
|
||||
UnlockMutex (maplock);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Fade Transforms */
|
||||
|
||||
int
|
||||
GetFadeAmount (void)
|
||||
{
|
||||
int newAmount;
|
||||
|
||||
LockMutex (XFormControl.Lock);
|
||||
|
||||
if (fadeInterval)
|
||||
{ // have a pending fade
|
||||
TimeCount Now = GetTimeCounter ();
|
||||
sint32 elapsed;
|
||||
|
||||
elapsed = Now - fadeStartTime;
|
||||
if (elapsed > fadeInterval)
|
||||
elapsed = fadeInterval;
|
||||
|
||||
newAmount = fadeAmount + (long)fadeDelta * elapsed / fadeInterval;
|
||||
|
||||
if (elapsed >= fadeInterval)
|
||||
{ // fade is over
|
||||
fadeAmount = newAmount;
|
||||
fadeInterval = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // no fade pending, return the current
|
||||
newAmount = fadeAmount;
|
||||
}
|
||||
|
||||
UnlockMutex (XFormControl.Lock);
|
||||
|
||||
return newAmount;
|
||||
}
|
||||
|
||||
static void
|
||||
finishPendingFade (void)
|
||||
{
|
||||
if (fadeInterval)
|
||||
{ // end the fade immediately
|
||||
fadeAmount += fadeDelta;
|
||||
fadeInterval = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
FlushFadeXForms (void)
|
||||
{
|
||||
LockMutex (XFormControl.Lock);
|
||||
finishPendingFade ();
|
||||
UnlockMutex (XFormControl.Lock);
|
||||
}
|
||||
|
||||
DWORD
|
||||
FadeScreen (ScreenFadeType fadeType, SIZE TimeInterval)
|
||||
{
|
||||
TimeCount TimeOut;
|
||||
int FadeEnd;
|
||||
|
||||
switch (fadeType)
|
||||
{
|
||||
case FadeAllToBlack:
|
||||
case FadeSomeToBlack:
|
||||
FadeEnd = FADE_NO_INTENSITY;
|
||||
break;
|
||||
case FadeAllToColor:
|
||||
case FadeSomeToColor:
|
||||
FadeEnd = FADE_NORMAL_INTENSITY;
|
||||
break;
|
||||
case FadeAllToWhite:
|
||||
case FadeSomeToWhite:
|
||||
FadeEnd = FADE_FULL_INTENSITY;
|
||||
break;
|
||||
default:
|
||||
return (GetTimeCounter ());
|
||||
}
|
||||
|
||||
// Don't make users wait for fades
|
||||
if (QuitPosted)
|
||||
TimeInterval = 0;
|
||||
|
||||
LockMutex (XFormControl.Lock);
|
||||
|
||||
finishPendingFade ();
|
||||
|
||||
if (TimeInterval <= 0)
|
||||
{ // end the fade immediately
|
||||
fadeAmount = FadeEnd;
|
||||
// cancel any pending fades
|
||||
fadeInterval = 0;
|
||||
TimeOut = GetTimeCounter ();
|
||||
}
|
||||
else
|
||||
{
|
||||
fadeInterval = TimeInterval;
|
||||
fadeDelta = FadeEnd - fadeAmount;
|
||||
fadeStartTime = GetTimeCounter ();
|
||||
TimeOut = fadeStartTime + TimeInterval + 1;
|
||||
}
|
||||
|
||||
UnlockMutex (XFormControl.Lock);
|
||||
|
||||
return TimeOut;
|
||||
}
|
||||
|
||||
/* Colormap Transforms */
|
||||
|
||||
static void
|
||||
finish_colormap_xform (int which)
|
||||
{
|
||||
SetColorMap (XFormControl.TaskControl[which].CMapPtr);
|
||||
XFormControl.TaskControl[which].CMapIndex = -1;
|
||||
// check Highest ptr
|
||||
if (which == XFormControl.Highest)
|
||||
{
|
||||
do
|
||||
--which;
|
||||
while (which >= 0 && XFormControl.TaskControl[which].CMapIndex == -1);
|
||||
|
||||
XFormControl.Highest = which;
|
||||
}
|
||||
}
|
||||
|
||||
static inline BYTE
|
||||
blendChan (BYTE c1, BYTE c2, int weight, int scale)
|
||||
{
|
||||
return c1 + ((int)c2 - c1) * weight / scale;
|
||||
}
|
||||
|
||||
/* This gives the XFormColorMap task a timeslice to do its thing
|
||||
* Only one thread should ever be allowed to be calling this at any time
|
||||
*/
|
||||
BOOLEAN
|
||||
XFormColorMap_step (void)
|
||||
{
|
||||
BOOLEAN Changed = FALSE;
|
||||
int x;
|
||||
DWORD Now = GetTimeCounter ();
|
||||
|
||||
LockMutex (XFormControl.Lock);
|
||||
|
||||
for (x = 0; x <= XFormControl.Highest; ++x)
|
||||
{
|
||||
XFORM_CONTROL *control = &XFormControl.TaskControl[x];
|
||||
int index = control->CMapIndex;
|
||||
int TicksLeft = control->EndTime - Now;
|
||||
TFB_ColorMap *curmap;
|
||||
|
||||
if (index < 0)
|
||||
continue; // unused slot
|
||||
|
||||
LockMutex (maplock);
|
||||
|
||||
curmap = colormaps[index];
|
||||
if (!curmap)
|
||||
{
|
||||
UnlockMutex (maplock);
|
||||
log_add (log_Error, "BUG: XFormColorMap_step(): no current map");
|
||||
finish_colormap_xform (x);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (TicksLeft > 0)
|
||||
{
|
||||
#define XFORM_SCALE 0x10000
|
||||
TFB_ColorMap *newmap = NULL;
|
||||
UBYTE *newClr;
|
||||
Color *oldClr;
|
||||
int frac;
|
||||
int i;
|
||||
|
||||
newmap = clone_colormap (curmap, index);
|
||||
|
||||
oldClr = control->OldCMap;
|
||||
newClr = (UBYTE*)control->CMapPtr + 2;
|
||||
|
||||
frac = (int)(control->Ticks - TicksLeft) * XFORM_SCALE
|
||||
/ control->Ticks;
|
||||
|
||||
for (i = 0; i < NUMBER_OF_PLUTVALS; ++i, ++oldClr,
|
||||
newClr += PLUTVAL_BYTE_SIZE)
|
||||
{
|
||||
Color color;
|
||||
|
||||
color.a = 0xff;
|
||||
color.r = blendChan (oldClr->r, newClr[PLUTVAL_RED],
|
||||
frac, XFORM_SCALE);
|
||||
color.g = blendChan (oldClr->g, newClr[PLUTVAL_GREEN],
|
||||
frac, XFORM_SCALE);
|
||||
color.b = blendChan (oldClr->b, newClr[PLUTVAL_BLUE],
|
||||
frac, XFORM_SCALE);
|
||||
SetNativePaletteColor (newmap->palette, i, color);
|
||||
}
|
||||
|
||||
colormaps[index] = newmap;
|
||||
release_colormap (curmap);
|
||||
}
|
||||
|
||||
UnlockMutex (maplock);
|
||||
|
||||
if (TicksLeft <= 0)
|
||||
{ // asked for immediate xform or already done
|
||||
finish_colormap_xform (x);
|
||||
}
|
||||
|
||||
Changed = TRUE;
|
||||
}
|
||||
|
||||
UnlockMutex (XFormControl.Lock);
|
||||
|
||||
return Changed;
|
||||
}
|
||||
|
||||
static void
|
||||
FlushPLUTXForms (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
LockMutex (XFormControl.Lock);
|
||||
|
||||
for (i = 0; i <= XFormControl.Highest; ++i)
|
||||
{
|
||||
if (XFormControl.TaskControl[i].CMapIndex >= 0)
|
||||
finish_colormap_xform (i);
|
||||
}
|
||||
XFormControl.Highest = -1; // all gone
|
||||
|
||||
UnlockMutex (XFormControl.Lock);
|
||||
}
|
||||
|
||||
static DWORD
|
||||
XFormPLUT (COLORMAPPTR ColorMapPtr, SIZE TimeInterval)
|
||||
{
|
||||
TFB_ColorMap *map;
|
||||
XFORM_CONTROL *control;
|
||||
int index;
|
||||
int x;
|
||||
int first_avail = -1;
|
||||
DWORD EndTime;
|
||||
DWORD Now;
|
||||
|
||||
Now = GetTimeCounter ();
|
||||
index = *(UBYTE*)ColorMapPtr;
|
||||
|
||||
LockMutex (XFormControl.Lock);
|
||||
// Find an available slot, or reuse if required
|
||||
for (x = 0; x <= XFormControl.Highest
|
||||
&& index != XFormControl.TaskControl[x].CMapIndex;
|
||||
++x)
|
||||
{
|
||||
if (first_avail == -1 && XFormControl.TaskControl[x].CMapIndex == -1)
|
||||
first_avail = x;
|
||||
}
|
||||
|
||||
if (index == XFormControl.TaskControl[x].CMapIndex)
|
||||
{ // already xforming this colormap -- cancel and reuse slot
|
||||
finish_colormap_xform (x);
|
||||
}
|
||||
else if (first_avail >= 0)
|
||||
{ // picked up a slot along the way
|
||||
x = first_avail;
|
||||
}
|
||||
else if (x >= MAX_XFORMS)
|
||||
{ // flush some xforms if the queue is full
|
||||
log_add (log_Debug, "WARNING: XFormPLUT(): no slots available");
|
||||
x = XFormControl.Highest;
|
||||
finish_colormap_xform (x);
|
||||
}
|
||||
// take next unused one
|
||||
control = &XFormControl.TaskControl[x];
|
||||
if (x > XFormControl.Highest)
|
||||
XFormControl.Highest = x;
|
||||
|
||||
// make a copy of the current map
|
||||
LockMutex (maplock);
|
||||
map = colormaps[index];
|
||||
if (!map)
|
||||
{
|
||||
UnlockMutex (maplock);
|
||||
UnlockMutex (XFormControl.Lock);
|
||||
log_add (log_Warning, "BUG: XFormPLUT(): no current map");
|
||||
return (0);
|
||||
}
|
||||
GetColorMapColors (control->OldCMap, map);
|
||||
UnlockMutex (maplock);
|
||||
|
||||
control->CMapIndex = index;
|
||||
control->CMapPtr = ColorMapPtr;
|
||||
control->Ticks = TimeInterval;
|
||||
if (control->Ticks < 0)
|
||||
control->Ticks = 0; /* prevent negative fade */
|
||||
control->StartTime = Now;
|
||||
control->EndTime = EndTime = Now + control->Ticks;
|
||||
|
||||
UnlockMutex (XFormControl.Lock);
|
||||
|
||||
return (EndTime);
|
||||
}
|
||||
|
||||
DWORD
|
||||
XFormColorMap (COLORMAPPTR ColorMapPtr, SIZE TimeInterval)
|
||||
{
|
||||
if (!ColorMapPtr)
|
||||
return (0);
|
||||
|
||||
// Don't make users wait for transforms
|
||||
if (QuitPosted)
|
||||
TimeInterval = 0;
|
||||
|
||||
return XFormPLUT (ColorMapPtr, TimeInterval);
|
||||
}
|
||||
|
||||
void
|
||||
FlushColorXForms (void)
|
||||
{
|
||||
FlushFadeXForms ();
|
||||
FlushPLUTXForms ();
|
||||
}
|
||||
|
||||
// The type conversions are implicit and will generate errors
|
||||
// or warnings if types change imcompatibly
|
||||
COLORMAPPTR
|
||||
GetColorMapAddress (COLORMAP colormap)
|
||||
{
|
||||
return GetStringAddress (colormap);
|
||||
}
|
||||
Reference in New Issue
Block a user