Added graphics context debugging function.

Plus small cleanups.



git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@3302 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
Meep-Eep
2009-11-14 22:17:24 +00:00
parent acbb2f7b25
commit 823c756b3c
17 changed files with 648 additions and 83 deletions
+16 -1
View File
@@ -169,8 +169,11 @@ extern void UninitGraphics (void);
extern CONTEXT SetContext (CONTEXT Context);
extern COLOR SetContextForeGroundColor (COLOR Color);
extern COLOR GetContextForeGroundColor (void);
extern COLOR SetContextBackGroundColor (COLOR Color);
extern COLOR GetContextBackGroundColor (void);
extern FRAME SetContextFGFrame (FRAME Frame);
extern FRAME GetContextFGFrame (void);
extern BOOLEAN SetContextClipping (BOOLEAN ClipStatus);
extern BOOLEAN SetContextClipRect (RECT *pRect);
extern BOOLEAN GetContextClipRect (RECT *pRect);
@@ -191,7 +194,13 @@ extern void UnbatchGraphics (void);
extern void FlushGraphics (void);
extern void ClearBackGround (RECT *pClipRect);
extern void ClearDrawable (void);
extern CONTEXT CreateContext (void);
#ifdef DEBUG
extern CONTEXT CreateContextAux (const char *name);
#define CreateContext(name) CreateContextAux((name))
#else /* if !defined(DEBUG) */
extern CONTEXT CreateContextAux (void);
#define CreateContext(name) CreateContextAux()
#endif /* !defined(DEBUG) */
extern BOOLEAN DestroyContext (CONTEXT ContextRef);
extern DRAWABLE CreateDisplay (CREATE_FLAGS CreateFlags, SIZE *pwidth,
SIZE *pheight);
@@ -199,6 +208,12 @@ extern DRAWABLE CreateDrawable (CREATE_FLAGS CreateFlags, SIZE width,
SIZE height, COUNT num_frames);
extern BOOLEAN DestroyDrawable (DRAWABLE Drawable);
extern BOOLEAN GetFrameRect (FRAME Frame, RECT *pRect);
#ifdef DEBUG
extern const char *GetContextName (CONTEXT context);
extern CONTEXT GetFirstContext (void);
extern CONTEXT GetNextContext (CONTEXT context);
extern size_t GetContextCount (void);
#endif /* DEBUG */
extern HOT_SPOT SetFrameHot (FRAME Frame, HOT_SPOT HotSpot);
extern HOT_SPOT GetFrameHot (FRAME Frame);
+94 -11
View File
@@ -22,6 +22,14 @@
GRAPHICS_STATUS _GraphicsStatusFlags;
CONTEXT _pCurContext;
#ifdef DEBUG
// We keep track of all contexts
CONTEXT firstContext;
// The first one in the list.
CONTEXT *contextEnd = &firstContext;
// Where to put the next context.
#endif
PRIMITIVE _locPrim;
FONT _CurFontPtr;
@@ -37,12 +45,10 @@ SetContext (CONTEXT Context)
if (LastContext)
{
UnsetContextFlags (
MAKE_WORD (0, GRAPHICS_ACTIVE | DRAWABLE_ACTIVE)
);
MAKE_WORD (0, GRAPHICS_ACTIVE | DRAWABLE_ACTIVE));
SetContextFlags (
MAKE_WORD (0, _GraphicsStatusFlags
& (GRAPHICS_ACTIVE | DRAWABLE_ACTIVE))
);
& (GRAPHICS_ACTIVE | DRAWABLE_ACTIVE)));
DeactivateContext ();
}
@@ -65,17 +71,29 @@ SetContext (CONTEXT Context)
return (LastContext);
}
#ifdef DEBUG
CONTEXT
CreateContext (void)
CreateContextAux (const char *name)
#else /* if !defined(DEBUG) */
CONTEXT
CreateContextAux (void)
#endif /* !defined(DEBUG) */
{
CONTEXT NewContext;
NewContext = AllocContext ();
if (NewContext)
{
/* initialize context */
CONTEXT OldContext;
/* initialize context */
#ifdef DEBUG
NewContext->name = name;
NewContext->next = NULL;
*contextEnd = NewContext;
contextEnd = &NewContext->next;
#endif /* DEBUG */
OldContext = SetContext (NewContext);
SetContextForeGroundColor (
BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F));
@@ -85,9 +103,25 @@ CreateContext (void)
SetContext (OldContext);
}
return (NewContext);
return NewContext;
}
#ifdef DEBUG
// Loop through the list of context to the pointer which points to the
// specified context. This is either 'firstContext' or the address of
// the 'next' field of some other context.
static CONTEXT *
FindContextPtr (CONTEXT context) {
CONTEXT *ptr;
for (ptr = &firstContext; *ptr != NULL; ptr = &(*ptr)->next) {
if (*ptr == context)
break;
}
return ptr;
}
#endif /* DEBUG */
BOOLEAN
DestroyContext (CONTEXT ContextRef)
{
@@ -97,6 +131,16 @@ DestroyContext (CONTEXT ContextRef)
if (_pCurContext && _pCurContext == ContextRef)
SetContext ((CONTEXT)0);
#ifdef DEBUG
// Unlink the context.
{
CONTEXT *contextPtr = FindContextPtr (ContextRef);
if (contextEnd == &ContextRef->next)
contextEnd = contextPtr;
*contextPtr = ContextRef->next;
}
#endif /* DEBUG */
FreeContext (ContextRef);
return TRUE;
}
@@ -109,7 +153,8 @@ SetContextForeGroundColor (COLOR Color)
if (!ContextActive ())
return (BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F));
if ((oldColor = _get_context_fg_color ()) != Color)
oldColor = _get_context_fg_color ();
if (oldColor != Color)
{
SwitchContextForeGroundColor (Color);
@@ -123,6 +168,15 @@ SetContextForeGroundColor (COLOR Color)
return (oldColor);
}
COLOR
GetContextForeGroundColor (void)
{
if (!ContextActive ())
return (BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F));
return _get_context_fg_color ();
}
COLOR
SetContextBackGroundColor (COLOR Color)
{
@@ -131,14 +185,22 @@ SetContextBackGroundColor (COLOR Color)
if (!ContextActive ())
return (BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00));
if ((oldColor = _get_context_bg_color ()) != Color)
{
oldColor = _get_context_bg_color ();
if (oldColor != Color)
SwitchContextBackGroundColor (Color);
}
return (oldColor);
}
COLOR
GetContextBackGroundColor (void)
{
if (!ContextActive ())
return (BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00));
return _get_context_bg_color ();
}
BOOLEAN
SetContextClipping (BOOLEAN ClipStatus)
{
@@ -249,3 +311,24 @@ FixContextFontEffect (void)
_pCurContext->FontBacking = img;
UnsetContextFBkFlags (FBK_DIRTY);
}
#ifdef DEBUG
const char *
GetContextName (CONTEXT context)
{
return context->name;
}
CONTEXT
GetFirstContext (void)
{
return firstContext;
}
CONTEXT
GetNextContext (CONTEXT context)
{
return context->next;
}
#endif /* DEBUG */
+4
View File
@@ -40,6 +40,10 @@ struct context_desc
TFB_Image *FontBacking;
FBK_FLAGS BackingFlags;
#ifdef DEBUG
const char *name;
CONTEXT next;
#endif
};
#define AllocContext() HCalloc (sizeof (CONTEXT_DESC))
+6
View File
@@ -51,6 +51,12 @@ SetContextFGFrame (FRAME Frame)
return (LastFrame);
}
FRAME
GetContextFGFrame (void)
{
return _CurFramePtr;
}
DRAWABLE
CreateDisplay (CREATE_FLAGS CreateFlags, SIZE *pwidth, SIZE *pheight)
{
+2 -2
View File
@@ -1266,7 +1266,7 @@ HailAlien (void)
SubtitleText.align = CommData.AlienTextAlign;
// init subtitle cache context
TextCacheContext = CreateContext ();
TextCacheContext = CreateContext ("TextCacheContext");
TextCacheFrame = CaptureDrawable (
CreateDrawable (WANT_PIXMAP, SIS_SCREEN_WIDTH,
SIS_SCREEN_HEIGHT - SLIDER_Y - SLIDER_HEIGHT + 2, 1));
@@ -1287,7 +1287,7 @@ HailAlien (void)
{
RECT r;
TaskContext = CreateContext ();
TaskContext = CreateContext ("TaskContext");
SetContext (TaskContext);
SetContextFGFrame (Screen);
GetFrameRect (CommData.AlienFrame, &r);
+2 -2
View File
@@ -315,8 +315,8 @@ credit_roll_task (void *data)
TextBack = BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00);
TextFore = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F);
LocalContext = CreateContext ();
DrawContext = CreateContext ();
LocalContext = CreateContext ("Credits.LocalContext");
DrawContext = CreateContext ("Credits.DrawContext");
total_h = disp_h = SCREEN_HEIGHT;
+14
View File
@@ -28,6 +28,7 @@
#include "settings.h"
#include "sounds.h"
#include "tactrans.h"
#include "uqmdebug.h"
#include "libs/inplib.h"
#include "libs/timelib.h"
#include "libs/threadlib.h"
@@ -352,6 +353,19 @@ DoInput (void *pInputState, BOOLEAN resetInput)
UpdateInputState ();
#ifdef DEBUG
if (doInputDebugHook != NULL)
{
void (*saveDebugHook) (void);
saveDebugHook = doInputDebugHook;
doInputDebugHook = NULL;
// No further debugHook calls unless the called
// function resets doInputDebugHook.
(*saveDebugHook) ();
continue;
}
#endif
#if DEMO_MODE || CREATE_JOURNAL
if (ArrowInput != DemoInput)
#endif
+1 -1
View File
@@ -125,7 +125,7 @@ CreateRadar (void)
RECT r;
CONTEXT OldContext;
RadarContext = CreateContext ();
RadarContext = CreateContext ("RadarContext");
OldContext = SetContext (RadarContext);
SetContextFGFrame (Screen);
r.corner.x = RADAR_X;
+1 -1
View File
@@ -110,7 +110,7 @@ GenerateChmmr (BYTE control)
CaptureStringTable (
LoadStringTable (CHMMR_BASE_STRTAB));
ScanContext = CreateContext ();
ScanContext = CreateContext ("genchmmr.ScanContext");
SetContext (ScanContext);
SetContextFGFrame (Screen);
r.corner.x = (SIS_ORG_X + SIS_SCREEN_WIDTH) - MAP_WIDTH;
+1 -1
View File
@@ -152,7 +152,7 @@ LoadPlanet (FRAME SurfDefFrame)
StopMusic ();
TaskContext = CreateContext ();
TaskContext = CreateContext ("TaskContext");
pPlanetDesc = pSolarSysState->pOrbitalDesc;
+1 -1
View File
@@ -1164,7 +1164,7 @@ ScanSystem (void)
(MAP_HEIGHT >> 1) << MAG_SHIFT;
LockMutex (GraphicsLock);
ScanContext = CreateContext ();
ScanContext = CreateContext ("ScanContext");
SetContext (ScanContext);
initPlanetLocationImage (&MenuState);
+4 -4
View File
@@ -96,7 +96,7 @@ LoadKernel (int argc, char *argv[])
InitSound (argc, argv);
InitVideoPlayer (TRUE);
ScreenContext = CreateContext ();
ScreenContext = CreateContext ("ScreenContext");
if (ScreenContext == NULL)
return FALSE;
@@ -158,7 +158,7 @@ InitContexts (void)
{
RECT r;
StatusContext = CreateContext ();
StatusContext = CreateContext ("StatusContext");
if (StatusContext == NULL)
return FALSE;
@@ -170,11 +170,11 @@ InitContexts (void)
r.extent.height = STATUS_HEIGHT;
SetContextClipRect (&r);
SpaceContext = CreateContext ();
SpaceContext = CreateContext ("SpaceContext");
if (SpaceContext == NULL)
return FALSE;
OffScreenContext = CreateContext ();
OffScreenContext = CreateContext ("OffScreenContext");
if (OffScreenContext == NULL)
return FALSE;
+52 -48
View File
@@ -761,7 +761,8 @@ DrawStorageBays (BOOLEAN Refresh)
--i;
}
r.extent.height = (4 * j + (STORAGE_BAY_CAPACITY - 1)) / STORAGE_BAY_CAPACITY;
r.extent.height = (4 * j + (STORAGE_BAY_CAPACITY - 1)) /
STORAGE_BAY_CAPACITY;
if (r.extent.height)
{
r.corner.y += 4 - r.extent.height;
@@ -876,14 +877,11 @@ DeltaSISGauges (SIZE crew_delta, SIZE fuel_delta, int resunit_delta)
s.origin.y = 0;
for (i = 0; i < NUM_DRIVE_SLOTS; ++i)
{
BYTE which_piece;
if ((which_piece =
GLOBAL_SIS (DriveSlots[i])) < EMPTY_SLOT)
BYTE which_piece = GLOBAL_SIS (DriveSlots[i]);
if (which_piece < EMPTY_SLOT)
{
s.frame = SetAbsFrameIndex (
FlagStatFrame, which_piece + 1 + 0
);
FlagStatFrame, which_piece + 1 + 0);
DrawStamp (&s);
s.frame = IncFrameIndex (s.frame);
DrawStamp (&s);
@@ -894,14 +892,11 @@ DeltaSISGauges (SIZE crew_delta, SIZE fuel_delta, int resunit_delta)
s.origin.y = 0;
for (i = 0; i < NUM_JET_SLOTS; ++i)
{
BYTE which_piece;
if ((which_piece =
GLOBAL_SIS (JetSlots[i])) < EMPTY_SLOT)
BYTE which_piece = GLOBAL_SIS (JetSlots[i]);
if (which_piece < EMPTY_SLOT)
{
s.frame = SetAbsFrameIndex (
FlagStatFrame, which_piece + 1 + 1
);
FlagStatFrame, which_piece + 1 + 1);
DrawStamp (&s);
s.frame = IncFrameIndex (s.frame);
DrawStamp (&s);
@@ -913,14 +908,11 @@ DeltaSISGauges (SIZE crew_delta, SIZE fuel_delta, int resunit_delta)
s.origin.x = 1; // This properly centers the modules.
for (i = 0; i < NUM_MODULE_SLOTS; ++i)
{
BYTE which_piece;
if ((which_piece =
GLOBAL_SIS (ModuleSlots[i])) < EMPTY_SLOT)
BYTE which_piece = GLOBAL_SIS (ModuleSlots[i]);
if (which_piece < EMPTY_SLOT)
{
s.frame = SetAbsFrameIndex (
FlagStatFrame, which_piece + 1 + 2
);
FlagStatFrame, which_piece + 1 + 2);
DrawStamp (&s);
}
@@ -996,22 +988,25 @@ DeltaSISGauges (SIZE crew_delta, SIZE fuel_delta, int resunit_delta)
old_coarse_fuel = (COUNT)~0;
else
{
DWORD FuelCapacity;
old_coarse_fuel = (COUNT)(
GLOBAL_SIS (FuelOnBoard) / FUEL_TANK_SCALE
);
GLOBAL_SIS (FuelOnBoard) / FUEL_TANK_SCALE);
if (fuel_delta < 0
&& GLOBAL_SIS (FuelOnBoard) <= (DWORD)-fuel_delta)
{
GLOBAL_SIS (FuelOnBoard) = 0;
else if ((GLOBAL_SIS (FuelOnBoard) += fuel_delta) >
(FuelCapacity = GetFTankCapacity (NULL)))
GLOBAL_SIS (FuelOnBoard) = FuelCapacity;
}
else
{
DWORD FuelCapacity = GetFTankCapacity (NULL);
GLOBAL_SIS (FuelOnBoard) += fuel_delta;
if (GLOBAL_SIS (FuelOnBoard) > FuelCapacity)
GLOBAL_SIS (FuelOnBoard) = FuelCapacity;
}
}
new_coarse_fuel = (COUNT)(
GLOBAL_SIS (FuelOnBoard) / FUEL_TANK_SCALE
);
GLOBAL_SIS (FuelOnBoard) / FUEL_TANK_SCALE);
if (new_coarse_fuel != old_coarse_fuel)
{
sprintf (buf, "%u", new_coarse_fuel);
@@ -1122,8 +1117,7 @@ GetCPodCapacity (POINT *ppt)
SetContextForeGroundColor (crew_rows[which_row]);
else
SetContextForeGroundColor (
BUILD_COLOR (MAKE_RGB15 (0x05, 0x10, 0x05), 0x65)
);
BUILD_COLOR (MAKE_RGB15 (0x05, 0x10, 0x05), 0x65));
}
capacity += CREW_POD_CAPACITY;
@@ -1169,7 +1163,8 @@ GetSBayCapacity (POINT *ppt)
};
bay_remainder = GLOBAL_SIS (TotalElementMass) - capacity;
if ((which_row = bay_remainder / SBAY_MASS_PER_ROW) == 0)
which_row = bay_remainder / SBAY_MASS_PER_ROW;
if (which_row == 0)
SetContextForeGroundColor (BLACK_COLOR);
else
SetContextForeGroundColor (color_bars[--which_row]);
@@ -1184,7 +1179,7 @@ GetSBayCapacity (POINT *ppt)
x -= SHIP_PIECE_OFFSET;
} while (slot--);
return (capacity);
return capacity;
}
DWORD
@@ -1229,8 +1224,7 @@ GetFTankCapacity (POINT *ppt)
which_row = (COUNT)(
(GLOBAL_SIS (FuelOnBoard) - capacity)
* MAX_FUEL_BARS / HEFUEL_TANK_CAPACITY
);
* MAX_FUEL_BARS / HEFUEL_TANK_CAPACITY);
ppt->x = x + 1;
if (volume == FUEL_TANK_CAPACITY)
ppt->y = 27 - which_row;
@@ -1247,7 +1241,7 @@ GetFTankCapacity (POINT *ppt)
x -= SHIP_PIECE_OFFSET;
} while (slot--);
return (capacity);
return capacity;
}
COUNT
@@ -1281,7 +1275,7 @@ CountSISPieces (BYTE piece_type)
}
}
return (num_pieces);
return num_pieces;
}
void
@@ -1356,6 +1350,7 @@ DrawAutoPilotMessage (BOOLEAN Reset)
Task flash_task = 0;
RECT flash_rect;
static FRAME flash_screen_frame = 0;
// The original contents of the flash rectangle.
static int flash_changed;
Mutex flash_mutex = 0;
// XXX: these are currently defined in libs/graphics/sdl/3do_getbody.c
@@ -1369,25 +1364,25 @@ flash_rect_func (void *data)
#define NORMAL_STRENGTH 4
#define NORMAL_F_STRENGTH 0
#define CACHE_SIZE 10
DWORD TimeIn, WaitTime;
SIZE strength, fstrength, incr;
DWORD TimeIn;
const DWORD WaitTime = ONE_SECOND / 16;
SIZE strength;
RECT cached_rect;
FRAME cached_screen_frame = 0;
Task task = (Task)data;
int cached[CACHE_SIZE];
bool cached[CACHE_SIZE];
STAMP cached_stamp[CACHE_SIZE];
int i;
// Init cache
for (i = 0; i < CACHE_SIZE; i++)
{
cached[i] = 0;
cached[i] = false;
cached_stamp[i].frame = 0;
}
fstrength = NORMAL_F_STRENGTH;
incr = 1;
strength = NORMAL_STRENGTH;
TimeIn = GetTimeCounter ();
WaitTime = ONE_SECOND / 16;
while (!Task_ReadState(task, TASK_EXIT))
{
CONTEXT OldContext;
@@ -1411,10 +1406,12 @@ flash_rect_func (void *data)
arith_frame_blit (flash_screen_frame, &screen_rect,
cached_screen_frame, NULL, 0, 0);
UnlockMutex (flash_mutex);
// Clear the cache.
for (i = 0; i < CACHE_SIZE; i++)
{
cached[i] = 0;
if(cached_stamp[i].frame)
cached[i] = false;
if (cached_stamp[i].frame)
DestroyDrawable (ReleaseDrawable (cached_stamp[i].frame));
cached_stamp[i].frame = 0;
}
@@ -1436,7 +1433,7 @@ flash_rect_func (void *data)
{
RECT tmp_rect = cached_rect;
pStamp = &cached_stamp[strength - MIN_STRENGTH];
cached[strength - MIN_STRENGTH] = 1;
cached[strength - MIN_STRENGTH] = true;
pStamp->frame = CaptureDrawable (CreateDrawable (WANT_PIXMAP,
cached_rect.extent.width, cached_rect.extent.height,
1));
@@ -1451,11 +1448,12 @@ flash_rect_func (void *data)
arith_frame_blit (cached_screen_frame, &tmp_rect,
pStamp->frame, &tmp_rect, strength, 4);
}
LockMutex (GraphicsLock);
OldContext = SetContext (ScreenContext);
SetContextClipRect (&cached_rect);
// flash changed_can't be modified while GraphicSem is held
if (! flash_changed)
if (!flash_changed)
DrawStamp (pStamp);
SetContextClipRect (NULL); // this will flush whatever
SetContext (OldContext);
@@ -1465,6 +1463,8 @@ flash_rect_func (void *data)
SleepThreadUntil (TimeIn + WaitTime);
TimeIn = GetTimeCounter ();
}
// Clear cache
{
if (cached_screen_frame)
DestroyDrawable (ReleaseDrawable (cached_screen_frame));
@@ -1480,7 +1480,7 @@ flash_rect_func (void *data)
UnlockMutex (flash_mutex);
FinishTask (task);
return(0);
return 0;
}
void
@@ -1490,7 +1490,7 @@ SetFlashRect (RECT *pRect)
CONTEXT OldContext;
int create_flash = 0;
if (! flash_mutex)
if (!flash_mutex)
flash_mutex = CreateMutex ("FlashRect Lock",
SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
@@ -1525,6 +1525,7 @@ SetFlashRect (RECT *pRect)
if (pRect == 0 || pRect->extent.width == 0)
{
// End the flashing.
flash_rect1.extent.width = 0;
if (flash_task)
{
@@ -1550,8 +1551,10 @@ SetFlashRect (RECT *pRect)
|| old_r.corner.x != flash_rect.corner.x
|| old_r.corner.y != flash_rect.corner.y))
{
// We had a flash rectangle, and now a different one is set.
if (flash_screen_frame)
{
// The screen contents may have changed; we grab a new copy.
STAMP old_s;
old_s.origin.x = old_r.corner.x;
old_s.origin.y = old_r.corner.y;
@@ -1566,6 +1569,7 @@ SetFlashRect (RECT *pRect)
if (flash_rect.extent.width)
{
// A new flash rectangle is set.
// Copy the original contents of the rectangle from the screen.
if (flash_screen_frame)
DestroyDrawable (ReleaseDrawable (flash_screen_frame));
+422 -5
View File
@@ -20,6 +20,7 @@
#include "build.h"
#include "colors.h"
#include "controls.h"
#include "clock.h"
#include "encount.h"
#include "element.h"
@@ -68,6 +69,7 @@ static void dumpPlanetTypeCallback (int index, const PlanetFrame *planet,
BOOLEAN instantMove = FALSE;
BOOLEAN disableInteractivity = FALSE;
void (* volatile debugHook) (void) = NULL;
void (* volatile doInputDebugHook) (void) = NULL;
void
@@ -118,6 +120,12 @@ debugKeyPressed (void)
// main loop. Calling it from here would give threading
// problems.
// Graphical and textual:
//doInputDebugHook = debugContexts;
// This will cause debugContexts to be called from the
// Starcon2Main thread, from DoInput(). Calling it from here
// would give threading problems.
// Interactive:
// uio_debugInteractive(stdin, stdout, stderr);
}
@@ -755,6 +763,7 @@ dumpUniverse (FILE *out)
UniverseRecurse (&universeRecurseArg);
}
// Must be called from the main thread.
void
dumpUniverseToFile (void)
{
@@ -1162,6 +1171,7 @@ tallyResources (FILE *out)
UniverseRecurse (&universeRecurseArg);
}
// Must be called from the main thread.
void
tallyResourcesToFile (void)
{
@@ -1459,7 +1469,8 @@ depositQualityString (BYTE quality)
// playerNr should be 0 or 1
STARSHIP*
findPlayerShip (SIZE playerNr) {
findPlayerShip (SIZE playerNr)
{
HELEMENT hElement, hNextElement;
for (hElement = GetHeadElement (); hElement; hElement = hNextElement)
@@ -1486,7 +1497,8 @@ findPlayerShip (SIZE playerNr) {
////////////////////////////////////////////////////////////////////////////
void
resetCrewBattle(void) {
resetCrewBattle (void)
{
STARSHIP *StarShipPtr;
COUNT delta;
CONTEXT OldContext;
@@ -1508,7 +1520,8 @@ resetCrewBattle(void) {
}
void
resetEnergyBattle(void) {
resetEnergyBattle (void)
{
STARSHIP *StarShipPtr;
COUNT delta;
CONTEXT OldContext;
@@ -1534,7 +1547,8 @@ resetEnergyBattle(void) {
// This function should help in making sure that gamestr.h matches
// gamestrings.txt.
void
dumpStrings(FILE *out) {
dumpStrings (FILE *out)
{
#define STRINGIZE(a) #a
#define MAKE_STRING_CATEGORY(prefix) \
{ \
@@ -1603,6 +1617,409 @@ dumpStrings(FILE *out) {
}
}
////////////////////////////////////////////////////////////////////////////
static COLOR
hsvaToRgba (double hue, double sat, double val, BYTE alpha) {
assert (hue >= 0.0 && hue < 360.0);
assert (sat >= 0 && sat <= 1.0);
assert (val >= 0 && val <= 1.0);
/*fprintf(stderr, "hsva = (%.1f, %.2f, %.2f, %.2d)\n",
hue, sat, val, alpha);*/
unsigned int hi = (int) (hue / 60.0);
double f = (hue / 60.0) - ((int) (hue / 60.0));
double p = val * (1.0 - sat);
double q = val * (1.0 - f * sat);
double t = val * (1.0 - (1.0 - f * sat));
// Convert p, q, t, and v from [0..1] to [0..255]
BYTE pb = (BYTE) (p * 255.0 + 0.5);
BYTE qb = (BYTE) (q * 255.0 + 0.5);
BYTE tb = (BYTE) (t * 255.0 + 0.5);
BYTE vb = (BYTE) (val * 255.0 + 0.5);
assert (hi < 6);
switch (hi) {
case 0: return BUILD_COLOR_RGBA (vb, tb, pb, alpha);
case 1: return BUILD_COLOR_RGBA (qb, vb, pb, alpha);
case 2: return BUILD_COLOR_RGBA (pb, vb, tb, alpha);
case 3: return BUILD_COLOR_RGBA (pb, qb, vb, alpha);
case 4: return BUILD_COLOR_RGBA (tb, pb, vb, alpha);
case 5: return BUILD_COLOR_RGBA (vb, pb, qb, alpha);
}
// Should not happen.
return BUILD_COLOR_RGBA (0, 0, 0, alpha);
}
// Work-around: colors returned by BUILD_COLOR_RGBA are not usable to draw
// with.
static DWORD
fixColorRgba (FRAME frame, COLOR col)
{
#if 0
extern DWORD frame_mapRGBA (FRAME FramePtr, BYTE r, BYTE g, BYTE b,
BYTE a);
BYTE r = (col & 0xff000000) >> 24;
BYTE g = (col & 0x00ff0000) >> 16;
BYTE b = (col & 0x0000ff00) >> 8;
BYTE a = (col & 0x000000ff) >> 0;
return (DWORD) frame_mapRGBA (frame, r, g, b, a);
#endif
BYTE r = (col & 0xff000000) >> 24;
BYTE g = (col & 0x00ff0000) >> 16;
BYTE b = (col & 0x0000ff00) >> 8;
(void) frame;
return BUILD_COLOR (MAKE_RGB15 (r >> 3, g >> 3, b >> 3) ,0);
}
// Workaround. DrawFilledRectangle() doesn't handle transparency.
// We use a temporary frame to achieve the same thing.
static void
DrawFilledRectangleTransparent (RECT *rect, BYTE alpha)
{
extern void arith_frame_blit (FRAME srcFrame, const RECT *rsrc,
FRAME dstFrame, const RECT *rdst, int num, int denom);
RECT absRect;
FRAME orgRectFrame;
COLOR fillColor;
// Create a rectangle from 'rect', but with (0, 0) as origin.
absRect.corner.x = 0;
absRect.corner.y = 0;
absRect.extent = rect->extent;
// Create a new temporary FRAME to store the contents of the original
// rectangle in.
orgRectFrame = CaptureDrawable (CreateDrawable (
WANT_PIXMAP, rect->extent.width, rect->extent.height, 1));
// Copy the original rectangle, faded.
arith_frame_blit (GetContextFGFrame (), rect, orgRectFrame, &absRect,
255 - alpha, 255);
// Apply the transparency to the colour.
fillColor = GetContextForeGroundColor ();
#if 0 /* 32 bits RGBA */
fillColor =
(((((fillColor & 0xff000000) >> 24) * alpha + 127) / 255) << 24) |
(((((fillColor & 0x00ff0000) >> 16) * alpha + 127) / 255) << 16) |
(((((fillColor & 0x0000ff00) >> 8) * alpha + 127) / 255) << 8);
*/
#endif
/* 15 bits RGB + index: */
fillColor =
(((((fillColor & 0x007c0000) >> 18) * alpha + 15) / 31) << 18) |
(((((fillColor & 0x0003e000) >> 13) * alpha + 15) / 31) << 13) |
(((((fillColor & 0x00001f00) >> 8) * alpha + 15) / 31) << 8) |
(fillColor & 0x000000ff);
// Fill the frame with fillColor
{
COLOR oldFgColor = SetContextForeGroundColor (fillColor);
DrawFilledRectangle (rect);
SetContextForeGroundColor (oldFgColor);
FlushGraphics ();
// Not really necessary for the Context for which this
// function is called, but if this function is ever used
// to draw directly to the screen, this will be needed
// to make sure the rectangle is drawn before the
// arith_frame_blit() call, which is immediate.
}
// Blend in the original rectangle.
arith_frame_blit (orgRectFrame, &absRect, GetContextFGFrame (), rect,
1, -1);
// Destroy the temporary frame
DestroyDrawable (ReleaseDrawable (orgRectFrame));
}
// Returns true iff this context has a visible FRAME.
static bool
isContextVisible (CONTEXT context)
{
FRAME contextFrame;
// Save the original context.
CONTEXT oldContext = SetContext (context);
// Get the frame of the specified context.
contextFrame = GetContextFGFrame ();
// Restore the original context.
SetContext (oldContext);
return contextFrame == Screen;
}
static size_t
countVisibleContexts (void)
{
size_t contextCount;
CONTEXT context;
contextCount = 0;
for (context = GetFirstContext (); context != NULL;
context = GetNextContext (context))
{
if (!isContextVisible (context))
continue;
contextCount++;
}
return contextCount;
}
static void
drawContext (CONTEXT context, double hue /* no pun intended */)
{
FRAME drawFrame;
CONTEXT oldContext;
FONT oldFont;
COLOR oldFgCol;
COLOR rectCol;
COLOR lineCol;
COLOR textCol;
bool haveClippingRect;
RECT rect;
LINE line;
TEXT text;
POINT p1, p2, p3, p4;
drawFrame = GetContextFGFrame ();
rectCol = (COLOR) fixColorRgba (drawFrame,
hsvaToRgba (hue, 1.0, 0.5, 127));
lineCol = (COLOR) fixColorRgba (drawFrame,
hsvaToRgba (hue, 1.0, 1.0, 0));
textCol = lineCol;
// Save the original context.
oldContext = SetContext (context);
// Get the clipping rectangle of the specified context.
haveClippingRect = GetContextClipRect (&rect);
// Switch back the old context; we're going to draw in it.
(void) SetContext (oldContext);
if (!haveClippingRect)
{
rect.corner.x = 0;
rect.corner.y = 0;
rect.extent.width = ScreenWidth;
rect.extent.height = ScreenHeight;
}
p1 = rect.corner;
p2.x = rect.corner.x + rect.extent.width - 1;
p2.y = rect.corner.y;
p3.x = rect.corner.x;
p3.y = rect.corner.y + rect.extent.height - 1;
p4.x = rect.corner.x + rect.extent.width - 1;
p4.y = rect.corner.y + rect.extent.height - 1;
oldFgCol = SetContextForeGroundColor (rectCol);
DrawFilledRectangleTransparent (&rect, 63);
SetContextForeGroundColor (lineCol);
line.first = p1; line.second = p2; DrawLine (&line);
line.first = p2; line.second = p4; DrawLine (&line);
line.first = p1; line.second = p3; DrawLine (&line);
line.first = p3; line.second = p4; DrawLine (&line);
line.first = p1; line.second = p4; DrawLine (&line);
line.first = p2; line.second = p3; DrawLine (&line);
// Gimme C'99! So I can do:
// DrawLine ((LINE) { .first = p1, .second = p2 })
oldFont = SetContextFont (TinyFont);
SetContextForeGroundColor (textCol);
text.baseline.x = (p1.x + (p2.x + 1)) / 2;
text.baseline.y = p1.y + 8;
text.pStr = GetContextName (context);
text.align = ALIGN_CENTER;
text.CharCount = (COUNT) ~0;
font_DrawText (&text);
(void) SetContextForeGroundColor (oldFgCol);
(void) SetContextFont (oldFont);
}
static void
describeContext (FILE *out, const CONTEXT context) {
RECT rect;
CONTEXT oldContext = SetContext (context);
GetContextClipRect (&rect);
fprintf(out, "Context '%s':\n"
"\tClipRect = (%d, %d)-(%d, %d) (%d x %d)\n",
GetContextName (context),
rect.corner.x, rect.corner.y,
rect.corner.x + rect.extent.width,
rect.corner.y + rect.extent.height,
rect.extent.width, rect.extent.height);
SetContext (oldContext);
}
typedef struct wait_state
{
// standard state required by DoInput
BOOLEAN (*InputFunc) (struct wait_state *self);
COUNT MenuRepeatDelay;
} WAIT_STATE;
// Maybe move to elsewhere, where it can be reused?
static BOOLEAN
waitForKey (struct wait_state *self) {
if (PulsedInputState.menu[KEY_MENU_SELECT] ||
PulsedInputState.menu[KEY_MENU_CANCEL])
return FALSE;
SleepThread (ONE_SECOND / 20);
(void) self;
return TRUE;
}
// Maybe move to elsewhere, where it can be reused?
static FRAME
getScreen (void)
{
CONTEXT oldContext = SetContext (ScreenContext);
FRAME savedFrame;
RECT screenRect;
screenRect.corner.x = 0;
screenRect.corner.y = 0;
screenRect.extent.width = ScreenWidth;
screenRect.extent.height = ScreenHeight;
savedFrame = CaptureDrawable (LoadDisplayPixmap (&screenRect, (FRAME) 0));
(void) SetContext (oldContext);
return savedFrame;
}
static void
putScreen (FRAME savedFrame) {
STAMP stamp;
CONTEXT oldContext = SetContext (ScreenContext);
stamp.origin.x = 0;
stamp.origin.y = 0;
stamp.frame = savedFrame;
DrawStamp (&stamp);
(void) SetContext (oldContext);
}
// Show the contexts on the screen.
// Must be called from the main thread.
void
debugContexts (void)
{
extern void arith_frame_blit (FRAME srcFrame, const RECT *rsrc,
FRAME dstFrame, const RECT *rdst, int num, int denom);
static volatile bool inDebugContexts = false;
// Prevent this function from being called from within itself.
CONTEXT orgContext;
CONTEXT debugDrawContext;
// We're going to use this context to draw in.
FRAME debugDrawFrame;
double hueIncrement;
size_t visibleContextI;
CONTEXT context;
size_t contextCount;
FRAME savedScreen;
// Prevent this function from being called from within itself.
if (inDebugContexts)
return;
inDebugContexts = true;
contextCount = countVisibleContexts ();
if (contextCount == 0)
goto out;
LockMutex (GraphicsLock);
savedScreen = getScreen ();
//UnlockMutex (GraphicsLock);
FlushGraphics ();
// Make sure that the screen has actually been captured,
// before we use the frame.
// Create a new frame to draw on.
debugDrawContext = CreateContext ("debugDrawContext");
debugDrawFrame = CaptureDrawable (CreateDrawable (
WANT_PIXMAP /*| WANT_ALPHA*/, ScreenWidth, ScreenHeight, 1));
orgContext = SetContext (debugDrawContext);
SetContextFGFrame (debugDrawFrame);
// Fill the new frame with a copy of the original.
arith_frame_blit (savedScreen, NULL, debugDrawFrame, NULL, 1, 1);
hueIncrement = 360.0 / contextCount;
//LockMutex (GraphicsLock);
visibleContextI = 0;
for (context = GetFirstContext (); context != NULL;
context = GetNextContext (context))
{
if (context == debugDrawContext) {
// Skip our own context.
continue;
}
if (isContextVisible (context))
{
// Only draw the visible contexts.
drawContext (context, visibleContextI * hueIncrement);
visibleContextI++;
}
describeContext (stderr, context);
}
// Blit the final debugging frame to the screen.
putScreen (debugDrawFrame);
UnlockMutex (GraphicsLock);
// Wait for a key:
{
WAIT_STATE state;
state.InputFunc = waitForKey;
DoInput(&state, TRUE);
}
SetContext (orgContext);
// Destroy the debugging frame and context.
DestroyContext (debugDrawContext);
// This does nothing with the drawable set with
// SetContextFGFrame().
DestroyDrawable (ReleaseDrawable (debugDrawFrame));
LockMutex (GraphicsLock);
putScreen (savedScreen);
UnlockMutex (GraphicsLock);
DestroyDrawable (ReleaseDrawable (savedScreen));
out:
inDebugContexts = false;
}
#endif /* DEBUG */
+11 -1
View File
@@ -29,9 +29,14 @@
// functions are a no-op.
extern BOOLEAN disableInteractivity;
// If a function is assigned to this, it will be called from the main loop.
// If a function is assigned to this, it will be called from the
// Starcon2Main thread, in the main game loop.
extern void (* volatile debugHook) (void);
// If a function is assigned to this, it will be called from the
// Starcon2Main thread, in doInput().
extern void (* volatile doInputDebugHook) (void);
// Called when the debug key (symbol 'Debug' in the keys.cfg) is pressed.
void debugKeyPressed (void);
@@ -180,6 +185,11 @@ extern BOOLEAN instantMove;
void dumpStrings(FILE *out);
// Graphically and textually show all the contexts.
// Should be called from debugHook.
void debugContexts (void);
// To add some day:
// - a function to fast forward the game clock to a specifiable time.