Switch SetFlashRect() to the new flash code, as the next step towards getting rid of threads. Also some small cleanups.

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@3749 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
Meep-Eep
2012-01-23 20:14:45 +00:00
parent ca5ead9d65
commit 20e2ea337f
9 changed files with 234 additions and 251 deletions
+2
View File
@@ -1,4 +1,6 @@
Changes towards version 0.8: Changes towards version 0.8:
- Switch SetFlashRect() to the new flash code -- SvdB
- Add C++ support to the build system, from Scott A. Colcord
- Cleaning up DoModifyShips() - SvdB - Cleaning up DoModifyShips() - SvdB
- Added Valgrind suppression file, from Louis Delacroix - Added Valgrind suppression file, from Louis Delacroix
- Fix several memory leaks, from Loius Delacroix - Fix several memory leaks, from Loius Delacroix
+10 -4
View File
@@ -18,6 +18,12 @@
// areas, drawing directly to the screen, using a cache, are // areas, drawing directly to the screen, using a cache, are
// currently in use. // currently in use.
// NOTE:
// - If you change the properties of the original CONTEXT, specifically the
// dimensions and origin, you'll need to call Flash_preUpdate() before and
// Flash_postUpdate() after that change. Note that this may change which
// part of the screen is flashing.
// TODO: // TODO:
// - During a few frames during the sequence, the frame to be displayed // - During a few frames during the sequence, the frame to be displayed
// is equal to a frame which was supplied as a parameter to the flash // is equal to a frame which was supplied as a parameter to the flash
@@ -472,7 +478,8 @@ Flash_setOverlay (FlashContext *context, const POINT *origin, FRAME overlay)
} }
} }
// Call before you update the graphics in the currently flashing area. // Call before you update the graphics in the currently flashing area,
// or before you change the dimensions or origin of the graphics context.
void void
Flash_preUpdate (FlashContext *context) Flash_preUpdate (FlashContext *context)
{ {
@@ -483,7 +490,8 @@ Flash_preUpdate (FlashContext *context)
} }
} }
// Call after you update the graphics in the currently flashing area. // Call after you update the graphics in the currently flashing area,
// or after you change the dimensions or origin of the graphics context.
void void
Flash_postUpdate (FlashContext *context) Flash_postUpdate (FlashContext *context)
{ {
@@ -803,5 +811,3 @@ Flash_drawCurrentFrame (FlashContext *context)
Flash_drawCachedFrame (context, numer, denom); Flash_drawCachedFrame (context, numer, denom);
} }
+31 -14
View File
@@ -176,6 +176,26 @@ FeedbackSetting (BYTE which_setting)
#define DDSHS_EDIT 1 #define DDSHS_EDIT 1
#define DDSHS_BLOCKCUR 2 #define DDSHS_BLOCKCUR 2
static const RECT captainNameRect = {
/* .corner = */ {
/* .x = */ 3,
/* .y = */ 10
}, /* .extent = */ {
/* .width = */ SHIP_NAME_WIDTH - 2,
/* .height = */ SHIP_NAME_HEIGHT
}
};
static const RECT shipNameRect = {
/* .corner = */ {
/* .x = */ 2,
/* .y = */ 20
}, /* .extent = */ {
/* .width = */ SHIP_NAME_WIDTH,
/* .height = */ SHIP_NAME_HEIGHT
}
};
static BOOLEAN static BOOLEAN
DrawNameString (bool nameCaptain, UNICODE *Str, COUNT CursorPos, DrawNameString (bool nameCaptain, UNICODE *Str, COUNT CursorPos,
COUNT state) COUNT state)
@@ -185,20 +205,11 @@ DrawNameString (bool nameCaptain, UNICODE *Str, COUNT CursorPos,
Color BackGround, ForeGround; Color BackGround, ForeGround;
FONT Font; FONT Font;
LockMutex (GraphicsLock);
{ {
r.corner.x = 2;
r.extent.width = SHIP_NAME_WIDTH;
r.extent.height = SHIP_NAME_HEIGHT;
SetContext (StatusContext);
if (nameCaptain) if (nameCaptain)
{ // Naming the captain { // Naming the captain
Font = TinyFont; Font = TinyFont;
r.corner.y = 10; r = captainNameRect;
++r.corner.x;
r.extent.width -= 2;
lf.baseline.x = r.corner.x + (r.extent.width >> 1) - 1; lf.baseline.x = r.corner.x + (r.extent.width >> 1) - 1;
BackGround = BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09); BackGround = BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09);
@@ -207,7 +218,7 @@ DrawNameString (bool nameCaptain, UNICODE *Str, COUNT CursorPos,
else else
{ // Naming the flagship { // Naming the flagship
Font = StarConFont; Font = StarConFont;
r.corner.y = 20; r = shipNameRect;
lf.baseline.x = r.corner.x + (r.extent.width >> 1); lf.baseline.x = r.corner.x + (r.extent.width >> 1);
BackGround = BUILD_COLOR (MAKE_RGB15 (0x0F, 0x00, 0x00), 0x2D); BackGround = BUILD_COLOR (MAKE_RGB15 (0x0F, 0x00, 0x00), 0x2D);
@@ -218,6 +229,8 @@ DrawNameString (bool nameCaptain, UNICODE *Str, COUNT CursorPos,
lf.align = ALIGN_CENTER; lf.align = ALIGN_CENTER;
} }
LockMutex (GraphicsLock);
SetContext (StatusContext);
SetContextFont (Font); SetContextFont (Font);
lf.pStr = Str; lf.pStr = Str;
lf.CharCount = (COUNT)~0; lf.CharCount = (COUNT)~0;
@@ -244,6 +257,10 @@ DrawNameString (bool nameCaptain, UNICODE *Str, COUNT CursorPos,
// disallow the change // disallow the change
return (FALSE); return (FALSE);
} }
UnlockMutex (GraphicsLock);
PreUpdateFlashRect ();
LockMutex (GraphicsLock);
SetContextForeGroundColor (BackGround); SetContextForeGroundColor (BackGround);
DrawFilledRectangle (&r); DrawFilledRectangle (&r);
@@ -281,8 +298,8 @@ DrawNameString (bool nameCaptain, UNICODE *Str, COUNT CursorPos,
SetContextForeGroundColor (ForeGround); SetContextForeGroundColor (ForeGround);
font_DrawText (&lf); font_DrawText (&lf);
SetFlashRect (&r); PostUpdateFlashRectLocked ();
} }
UnlockMutex (GraphicsLock); UnlockMutex (GraphicsLock);
@@ -309,7 +326,7 @@ NameCaptainOrShip (bool nameCaptain)
UNICODE *Setting; UNICODE *Setting;
LockMutex (GraphicsLock); LockMutex (GraphicsLock);
SetFlashRect (NULL); SetFlashRect (nameCaptain ? &captainNameRect : &shipNameRect);
UnlockMutex (GraphicsLock); UnlockMutex (GraphicsLock);
DrawNameString (nameCaptain, buf, 0, DDSHS_EDIT); DrawNameString (nameCaptain, buf, 0, DDSHS_EDIT);
+2 -9
View File
@@ -28,9 +28,6 @@
#include "libs/tasklib.h" #include "libs/tasklib.h"
#include "libs/log.h" #include "libs/log.h"
extern Task flash_task;
extern RECT flash_rect;
static BYTE GetEndMenuState (BYTE BaseState); static BYTE GetEndMenuState (BYTE BaseState);
static BYTE GetBeginMenuState (BYTE BaseState); static BYTE GetBeginMenuState (BYTE BaseState);
static BYTE FixMenuState (BYTE BadState); static BYTE FixMenuState (BYTE BadState);
@@ -500,6 +497,7 @@ DrawMenuStateStrings (BYTE beg_index, SWORD NewState)
if (NewState <= end_index - beg_index) if (NewState <= end_index - beg_index)
s.frame = SetAbsFrameIndex (PlayFrame, beg_index + NewState); s.frame = SetAbsFrameIndex (PlayFrame, beg_index + NewState);
PreUpdateFlashRect ();
LockMutex (GraphicsLock); LockMutex (GraphicsLock);
OldContext = SetContext (StatusContext); OldContext = SetContext (StatusContext);
GetContextClipRect (&r); GetContextClipRect (&r);
@@ -600,13 +598,8 @@ DrawMenuStateStrings (BYTE beg_index, SWORD NewState)
} }
} }
UnbatchGraphics (); UnbatchGraphics ();
if (flash_task
&& flash_rect.corner.x == RADAR_X
&& flash_rect.corner.y == RADAR_Y
&& flash_rect.extent.width == RADAR_WIDTH
&& flash_rect.extent.height == RADAR_HEIGHT)
SetFlashRect (SFR_MENU_3DO);
SetContext (OldContext); SetContext (OldContext);
UnlockMutex (GraphicsLock); UnlockMutex (GraphicsLock);
PostUpdateFlashRect ();
} }
+6 -2
View File
@@ -448,9 +448,9 @@ DoInstallModule (MENU_STATE *pMS)
if (NewItem != pMS->CurState) if (NewItem != pMS->CurState)
{ {
pMS->CurState = NewItem; pMS->CurState = NewItem;
PreUpdateFlashRect ();
DrawModuleStrings (pMS, NewItem); DrawModuleStrings (pMS, NewItem);
// flash with PC menus too PostUpdateFlashRect ();
SetFlashRect (SFR_MENU_ANY);
} }
} }
else if (NewItem != pMS->delta_item || NewState != pMS->CurState) else if (NewItem != pMS->delta_item || NewState != pMS->CurState)
@@ -573,7 +573,9 @@ ChangeFuelQuantity (void)
SetContextBackGroundColor (BLACK_COLOR)); SetContextBackGroundColor (BLACK_COLOR));
DrawFilledRectangle (&r); DrawFilledRectangle (&r);
} }
PreUpdateFlashRect ();
DeltaSISGauges (0, FUEL_TANK_SCALE, -GLOBAL (FuelCost)); DeltaSISGauges (0, FUEL_TANK_SCALE, -GLOBAL (FuelCost));
PostUpdateFlashRect ();
SetContext (StatusContext); SetContext (StatusContext);
GetGaugeRect (&r, FALSE); GetGaugeRect (&r, FALSE);
SetFlashRect (&r); SetFlashRect (&r);
@@ -590,7 +592,9 @@ ChangeFuelQuantity (void)
SetContext (SpaceContext); SetContext (SpaceContext);
if (GLOBAL_SIS (FuelOnBoard)) if (GLOBAL_SIS (FuelOnBoard))
{ {
PreUpdateFlashRect ();
DeltaSISGauges (0, -FUEL_TANK_SCALE, GLOBAL (FuelCost)); DeltaSISGauges (0, -FUEL_TANK_SCALE, GLOBAL (FuelCost));
PostUpdateFlashRect ();
if (GLOBAL_SIS (FuelOnBoard) % FUEL_VOLUME_PER_ROW == 0 && if (GLOBAL_SIS (FuelOnBoard) % FUEL_VOLUME_PER_ROW == 0 &&
GLOBAL_SIS (FuelOnBoard) >= FUEL_RESERVE) GLOBAL_SIS (FuelOnBoard) >= FUEL_RESERVE)
{ {
+2
View File
@@ -198,7 +198,9 @@ DeltaSupportCrew (ROSTER_STATE *rosterState, SIZE crew_delta)
StarShipPtr->crew_level, StarShipPtr->crew_level,
TemplatePtr->crew_level); TemplatePtr->crew_level);
PreUpdateFlashRect ();
DrawStatusMessage (buf); DrawStatusMessage (buf);
PostUpdateFlashRect ();
DeltaSISGauges (-crew_delta, 0, 0); DeltaSISGauges (-crew_delta, 0, 0);
if (crew_delta) if (crew_delta)
{ {
+53 -24
View File
@@ -219,8 +219,7 @@ DrawRaceStrings (MENU_STATE *pMS, BYTE NewRaceItem)
r.corner = s.origin; r.corner = s.origin;
r.extent.width = RADAR_WIDTH; r.extent.width = RADAR_WIDTH;
r.extent.height = RADAR_HEIGHT; r.extent.height = RADAR_HEIGHT;
SetContextForeGroundColor ( SetContextForeGroundColor (BLACK_COLOR);
BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00));
DrawFilledRectangle (&r); DrawFilledRectangle (&r);
if (NewRaceItem != (BYTE)~0) if (NewRaceItem != (BYTE)~0)
{ {
@@ -232,19 +231,22 @@ DrawRaceStrings (MENU_STATE *pMS, BYTE NewRaceItem)
hStarShip = GetAvailableRaceFromIndex (NewRaceItem); hStarShip = GetAvailableRaceFromIndex (NewRaceItem);
NewRaceItem = GetIndexFromStarShip (&GLOBAL (avail_race_q), NewRaceItem = GetIndexFromStarShip (&GLOBAL (avail_race_q),
hStarShip); hStarShip);
// Draw the ship name, above the ship image.
s.frame = SetAbsFrameIndex (pMS->ModuleFrame, 3 + NewRaceItem); s.frame = SetAbsFrameIndex (pMS->ModuleFrame, 3 + NewRaceItem);
// Ship name, above the ship image.
DrawStamp (&s); DrawStamp (&s);
// Draw the ship image.
FleetPtr = LockFleetInfo (&GLOBAL (avail_race_q), hStarShip); FleetPtr = LockFleetInfo (&GLOBAL (avail_race_q), hStarShip);
s.frame = FleetPtr->melee_icon; s.frame = FleetPtr->melee_icon;
// Ship image.
UnlockFleetInfo (&GLOBAL (avail_race_q), hStarShip); UnlockFleetInfo (&GLOBAL (avail_race_q), hStarShip);
t.baseline.x = s.origin.x + RADAR_WIDTH - 2; t.baseline.x = s.origin.x + RADAR_WIDTH - 2;
t.baseline.y = s.origin.y + RADAR_HEIGHT - 2; t.baseline.y = s.origin.y + RADAR_HEIGHT - 2;
s.origin.x += (RADAR_WIDTH >> 1); s.origin.x += (RADAR_WIDTH >> 1);
s.origin.y += (RADAR_HEIGHT >> 1); s.origin.y += (RADAR_HEIGHT >> 1);
DrawStamp (&s); DrawStamp (&s);
// Print the ship cost.
t.align = ALIGN_RIGHT; t.align = ALIGN_RIGHT;
t.CharCount = (COUNT)~0; t.CharCount = (COUNT)~0;
t.pStr = buf; t.pStr = buf;
@@ -257,8 +259,6 @@ DrawRaceStrings (MENU_STATE *pMS, BYTE NewRaceItem)
UnbatchGraphics (); UnbatchGraphics ();
SetContext (OldContext); SetContext (OldContext);
// Flash the ship purchase menu even when optMenu == OPT_PC
SetFlashRect (SFR_MENU_ANY);
UnlockMutex (GraphicsLock); UnlockMutex (GraphicsLock);
} }
@@ -266,6 +266,10 @@ DrawRaceStrings (MENU_STATE *pMS, BYTE NewRaceItem)
#define SHIP_WIN_HEIGHT (SHIP_WIN_WIDTH + 6) #define SHIP_WIN_HEIGHT (SHIP_WIN_WIDTH + 6)
#define SHIP_WIN_FRAMES ((SHIP_WIN_WIDTH >> 1) + 1) #define SHIP_WIN_FRAMES ((SHIP_WIN_WIDTH >> 1) + 1)
// Print the crew count of an escort ship on top of its (already drawn)
// image, either as '30' (full), '28/30' (partially full), or 'SCRAP'
// (empty).
// pRect is the rectangle of the ship image.
static void static void
ShowShipCrew (SHIP_FRAGMENT *StarShipPtr, const RECT *pRect) ShowShipCrew (SHIP_FRAGMENT *StarShipPtr, const RECT *pRect)
{ {
@@ -274,20 +278,21 @@ ShowShipCrew (SHIP_FRAGMENT *StarShipPtr, const RECT *pRect)
UNICODE buf[80]; UNICODE buf[80];
HFLEETINFO hTemplate; HFLEETINFO hTemplate;
FLEET_INFO *TemplatePtr; FLEET_INFO *TemplatePtr;
COUNT maxCrewLevel;
hTemplate = GetStarShipFromIndex (&GLOBAL (avail_race_q), hTemplate = GetStarShipFromIndex (&GLOBAL (avail_race_q),
StarShipPtr->race_id); StarShipPtr->race_id);
TemplatePtr = LockFleetInfo (&GLOBAL (avail_race_q), hTemplate); TemplatePtr = LockFleetInfo (&GLOBAL (avail_race_q), hTemplate);
if (StarShipPtr->crew_level >= TemplatePtr->crew_level) maxCrewLevel = TemplatePtr->crew_level;
UnlockFleetInfo (&GLOBAL (avail_race_q), hTemplate);
if (StarShipPtr->crew_level >= maxCrewLevel)
sprintf (buf, "%u", StarShipPtr->crew_level); sprintf (buf, "%u", StarShipPtr->crew_level);
else if (StarShipPtr->crew_level == 0) else if (StarShipPtr->crew_level == 0)
// XXX: "SCRAP" needs to be moved to starcon.txt // XXX: "SCRAP" needs to be moved to starcon.txt
utf8StringCopy (buf, sizeof (buf), "SCRAP"); utf8StringCopy (buf, sizeof (buf), "SCRAP");
else else
sprintf (buf, "%u/%u", sprintf (buf, "%u/%u", StarShipPtr->crew_level, maxCrewLevel);
StarShipPtr->crew_level,
TemplatePtr->crew_level);
UnlockFleetInfo (&GLOBAL (avail_race_q), hTemplate);
r = *pRect; r = *pRect;
t.baseline.x = r.corner.x + (r.extent.width >> 1); t.baseline.x = r.corner.x + (r.extent.width >> 1);
@@ -313,14 +318,17 @@ static void
ShowCombatShip (MENU_STATE *pMS, COUNT which_window, ShowCombatShip (MENU_STATE *pMS, COUNT which_window,
SHIP_FRAGMENT *YankedStarShipPtr) SHIP_FRAGMENT *YankedStarShipPtr)
{ {
COUNT i, num_ships; COUNT i;
COUNT num_ships;
HSHIPFRAG hStarShip, hNextShip; HSHIPFRAG hStarShip, hNextShip;
SHIP_FRAGMENT *StarShipPtr; SHIP_FRAGMENT *StarShipPtr;
struct struct
{ {
SHIP_FRAGMENT *StarShipPtr; SHIP_FRAGMENT *StarShipPtr;
POINT finished_s; POINT finished_s;
STAMP ship_s, lfdoor_s, rtdoor_s; STAMP ship_s;
STAMP lfdoor_s;
STAMP rtdoor_s;
} ship_win_info[MAX_BUILT_SHIPS], *pship_win_info; } ship_win_info[MAX_BUILT_SHIPS], *pship_win_info;
num_ships = 1; num_ships = 1;
@@ -388,6 +396,10 @@ ShowCombatShip (MENU_STATE *pMS, COUNT which_window,
hNextShip = _GetSuccLink (StarShipPtr); hNextShip = _GetSuccLink (StarShipPtr);
pship_win_info->StarShipPtr = StarShipPtr; pship_win_info->StarShipPtr = StarShipPtr;
// XXX BUG: this looks wrong according to the original
// semantics of LockShipFrag(): StarShipPtr is not valid
// anymore after UnlockShipFrag() is called, but it is
// used thereafter.
pship_win_info->lfdoor_s.origin.x = -1; pship_win_info->lfdoor_s.origin.x = -1;
pship_win_info->rtdoor_s.origin.x = 1; pship_win_info->rtdoor_s.origin.x = 1;
@@ -496,6 +508,7 @@ ShowCombatShip (MENU_STATE *pMS, COUNT which_window,
} }
} }
// Pre: GraphicsLock is unlocked.
static void static void
CrewTransaction (SIZE crew_delta) CrewTransaction (SIZE crew_delta)
{ {
@@ -519,10 +532,7 @@ CrewTransaction (SIZE crew_delta)
&& crew_bought - crew_delta < CREW_EXPENSE_THRESHOLD) && crew_bought - crew_delta < CREW_EXPENSE_THRESHOLD)
{ {
GLOBAL (CrewCost) += 2; GLOBAL (CrewCost) += 2;
UnlockMutex (GraphicsLock);
DrawMenuStateStrings (PM_CREW, SHIPYARD_CREW); DrawMenuStateStrings (PM_CREW, SHIPYARD_CREW);
LockMutex (GraphicsLock);
} }
} }
else else
@@ -531,10 +541,7 @@ CrewTransaction (SIZE crew_delta)
&& crew_bought - crew_delta >= CREW_EXPENSE_THRESHOLD) && crew_bought - crew_delta >= CREW_EXPENSE_THRESHOLD)
{ {
GLOBAL (CrewCost) -= 2; GLOBAL (CrewCost) -= 2;
UnlockMutex (GraphicsLock);
DrawMenuStateStrings (PM_CREW, SHIPYARD_CREW); DrawMenuStateStrings (PM_CREW, SHIPYARD_CREW);
LockMutex (GraphicsLock);
} }
} }
if (CheckAlliance (SHOFIXTI_SHIP) != GOOD_GUY) if (CheckAlliance (SHOFIXTI_SHIP) != GOOD_GUY)
@@ -739,8 +746,14 @@ DMS_HireFlagShipCrew (void)
return 0; return 0;
} }
// Draw a crew member.
DrawPoint (&r.corner); DrawPoint (&r.corner);
// Update the crew counter and RU. Note that the crew counter is
// flashing.
PreUpdateFlashRectLocked ();
DeltaSISGauges (1, 0, -GLOBAL (CrewCost)); DeltaSISGauges (1, 0, -GLOBAL (CrewCost));
PostUpdateFlashRectLocked ();
return 1; return 1;
} }
@@ -765,9 +778,14 @@ DMS_DismissFlagShipCrew (void)
GET_GAME_STATE (CREW_PURCHASED0), GET_GAME_STATE (CREW_PURCHASED0),
GET_GAME_STATE (CREW_PURCHASED1)); GET_GAME_STATE (CREW_PURCHASED1));
// Update the crew counter and RU. Note that the crew counter is
// flashing.
PreUpdateFlashRectLocked ();
DeltaSISGauges (-1, 0, GLOBAL (CrewCost) - DeltaSISGauges (-1, 0, GLOBAL (CrewCost) -
(crew_bought == CREW_EXPENSE_THRESHOLD ? 2 : 0)); (crew_bought == CREW_EXPENSE_THRESHOLD ? 2 : 0));
PostUpdateFlashRectLocked ();
// Remove the pixel representing the crew member.
GetCPodCapacity (&r.corner); GetCPodCapacity (&r.corner);
SetContextForeGroundColor (BLACK_COLOR); SetContextForeGroundColor (BLACK_COLOR);
DrawPoint (&r.corner); DrawPoint (&r.corner);
@@ -824,8 +842,11 @@ DMS_HireEscortShipCrew (SHIP_FRAGMENT *StarShipPtr)
} }
++StarShipPtr->crew_level; ++StarShipPtr->crew_level;
PreUpdateFlashRectLocked ();
DMS_GetEscortShipRect (&r, StarShipPtr->index); DMS_GetEscortShipRect (&r, StarShipPtr->index);
ShowShipCrew (StarShipPtr, &r); ShowShipCrew (StarShipPtr, &r);
PostUpdateFlashRectLocked ();
return 1; return 1;
} }
@@ -867,8 +888,10 @@ DMS_DismissEscortShipCrew (SHIP_FRAGMENT *StarShipPtr)
PlayMenuSound (MENU_SOUND_FAILURE); PlayMenuSound (MENU_SOUND_FAILURE);
} }
PreUpdateFlashRectLocked ();
DMS_GetEscortShipRect (&r, StarShipPtr->index); DMS_GetEscortShipRect (&r, StarShipPtr->index);
ShowShipCrew (StarShipPtr, &r); ShowShipCrew (StarShipPtr, &r);
PostUpdateFlashRectLocked ();
return crew_delta; return crew_delta;
} }
@@ -880,6 +903,7 @@ DMS_DismissEscortShipCrew (SHIP_FRAGMENT *StarShipPtr)
// selected. // selected.
// 'dy' is -1 if the 'up' button was pressed, or '1' if the down button was // 'dy' is -1 if the 'up' button was pressed, or '1' if the down button was
// pressed. // pressed.
// Pre: caller holds the GraphicsLock
static void static void
DMS_ModifyCrew (MENU_STATE *pMS, HSHIPFRAG hStarShip, SBYTE dy) DMS_ModifyCrew (MENU_STATE *pMS, HSHIPFRAG hStarShip, SBYTE dy)
{ {
@@ -936,12 +960,15 @@ DMS_ModifyCrew (MENU_STATE *pMS, HSHIPFRAG hStarShip, SBYTE dy)
pMS->delta_item &= MODIFY_CREW_FLAG; pMS->delta_item &= MODIFY_CREW_FLAG;
} }
UnlockMutex (GraphicsLock);
CrewTransaction (crew_delta); CrewTransaction (crew_delta);
LockMutex (GraphicsLock);
} }
// Helper function for DoModifyShips(), called when the player presses the // Helper function for DoModifyShips(), called when the player presses the
// select button when the cursor is over an empty escort ship slot. // select button when the cursor is over an empty escort ship slot.
// Try to add the currently selected ship as an escort ship. // Try to add the currently selected ship as an escort ship.
// Pre: caller does not hold the GraphicsLock
static void static void
DMS_TryAddEscortShip (MENU_STATE *pMS) DMS_TryAddEscortShip (MENU_STATE *pMS)
{ {
@@ -1000,7 +1027,7 @@ DMS_AddEscortShip (MENU_STATE *pMS, BOOLEAN special, BOOLEAN select,
// Cancel selecting an escort ship. // Cancel selecting an escort ship.
pMS->delta_item &= ~MODIFY_CREW_FLAG; pMS->delta_item &= ~MODIFY_CREW_FLAG;
LockMutex (GraphicsLock); LockMutex (GraphicsLock);
SetFlashRect (SFR_MENU_3DO); SetFlashRect (NULL);
UnlockMutex (GraphicsLock); UnlockMutex (GraphicsLock);
DrawMenuStateStrings (PM_CREW, SHIPYARD_CREW); DrawMenuStateStrings (PM_CREW, SHIPYARD_CREW);
LockMutex (GraphicsLock); LockMutex (GraphicsLock);
@@ -1032,7 +1059,9 @@ DMS_AddEscortShip (MENU_STATE *pMS, BOOLEAN special, BOOLEAN select,
if (currentShip != LOBYTE (pMS->delta_item)) if (currentShip != LOBYTE (pMS->delta_item))
{ {
PreUpdateFlashRect ();
DrawRaceStrings (pMS, currentShip); DrawRaceStrings (pMS, currentShip);
PostUpdateFlashRect ();
pMS->delta_item = currentShip | MODIFY_CREW_FLAG; pMS->delta_item = currentShip | MODIFY_CREW_FLAG;
} }
} }
@@ -1041,6 +1070,7 @@ DMS_AddEscortShip (MENU_STATE *pMS, BOOLEAN special, BOOLEAN select,
// Helper function for DoModifyShips(), called when the player presses // Helper function for DoModifyShips(), called when the player presses
// 'select' or 'cancel' after selling all the crew. // 'select' or 'cancel' after selling all the crew.
// Pre: caller holds the GraphicsLock
static void static void
DMS_ScrapEscortShip (MENU_STATE *pMS, HSHIPFRAG hStarShip) DMS_ScrapEscortShip (MENU_STATE *pMS, HSHIPFRAG hStarShip)
{ {
@@ -1108,6 +1138,7 @@ DMS_MoveCursor (BYTE curState, SBYTE dx, SBYTE dy)
// Helper function for DoModifyShips(), called every time DoModifyShip() is // Helper function for DoModifyShips(), called every time DoModifyShip() is
// called when we are in crew editing mode. // called when we are in crew editing mode.
// Pre: Caller holds the GraphicsLock
static void static void
DMS_EditCrewMode (MENU_STATE *pMS, HSHIPFRAG hStarShip, DMS_EditCrewMode (MENU_STATE *pMS, HSHIPFRAG hStarShip,
BOOLEAN select, BOOLEAN cancel, SBYTE dy) BOOLEAN select, BOOLEAN cancel, SBYTE dy)
@@ -1132,9 +1163,7 @@ DMS_EditCrewMode (MENU_STATE *pMS, HSHIPFRAG hStarShip,
} }
pMS->delta_item &= ~MODIFY_CREW_FLAG; pMS->delta_item &= ~MODIFY_CREW_FLAG;
LockMutex (GraphicsLock);
DMS_SetMode (pMS, DMS_Mode_navigate); DMS_SetMode (pMS, DMS_Mode_navigate);
UnlockMutex (GraphicsLock);
} }
else if (dy) else if (dy)
{ {
@@ -1146,7 +1175,7 @@ DMS_EditCrewMode (MENU_STATE *pMS, HSHIPFRAG hStarShip,
// Helper function for DoModifyShips(), called every time DoModifyShip() is // Helper function for DoModifyShips(), called every time DoModifyShip() is
// called when we are in the mode where you can select a ship or empty slot. // called when we are in the mode where you can select a ship or empty slot.
void static void
DMS_NavigateShipSlots (MENU_STATE *pMS, BOOLEAN special, BOOLEAN select, DMS_NavigateShipSlots (MENU_STATE *pMS, BOOLEAN special, BOOLEAN select,
BOOLEAN cancel, SBYTE dx, SBYTE dy) BOOLEAN cancel, SBYTE dx, SBYTE dy)
{ {
+123 -197
View File
@@ -31,6 +31,7 @@
#include "element.h" #include "element.h"
#include "setup.h" #include "setup.h"
#include "state.h" #include "state.h"
#include "flash.h"
#include "libs/graphics/gfx_common.h" #include "libs/graphics/gfx_common.h"
#include "libs/tasklib.h" #include "libs/tasklib.h"
#include "libs/log.h" #include "libs/log.h"
@@ -1589,248 +1590,173 @@ DrawAutoPilotMessage (BOOLEAN Reset)
} }
Task flash_task = 0; static Task flash_task = 0;
RECT flash_rect; static FlashContext *flashContext = NULL;
static FRAME flash_screen_frame = 0; static RECT flash_rect;
// The original contents of the flash rectangle. static Mutex flash_mutex = 0;
static int flash_changed;
Mutex flash_mutex = 0;
static int static int
flash_rect_func (void *data) flash_rect_func (void *data)
{ {
#define NORMAL_STRENGTH 4
#define NORMAL_F_STRENGTH 0
#define CACHE_SIZE 10
DWORD TimeIn;
const DWORD WaitTime = ONE_SECOND / 16;
SIZE strength;
RECT cached_rect = {{0, 0}, {0, 0}};
FRAME cached_screen_frame = 0;
Task task = (Task)data; Task task = (Task)data;
bool cached[CACHE_SIZE];
STAMP cached_stamp[CACHE_SIZE];
int i;
// Init cache
for (i = 0; i < CACHE_SIZE; i++)
{
cached[i] = false;
cached_stamp[i].frame = 0;
}
strength = NORMAL_STRENGTH;
TimeIn = GetTimeCounter ();
while (!Task_ReadState(task, TASK_EXIT)) while (!Task_ReadState(task, TASK_EXIT))
{ {
CONTEXT OldContext; TimeCount nextTime;
LockMutex (flash_mutex); LockMutex (flash_mutex);
if (flash_changed) Flash_process (flashContext);
{ nextTime = Flash_nextTime (flashContext);
cached_rect = flash_rect; UnlockMutex (flash_mutex);
if (cached_screen_frame) SleepThreadUntil (nextTime);
DestroyDrawable (ReleaseDrawable (cached_screen_frame));
flash_changed = 0;
// Wait for the flash_screen_frame to get initialized
FlushGraphics ();
cached_screen_frame = CaptureDrawable (
CloneFrame (flash_screen_frame));
UnlockMutex (flash_mutex);
// Clear the cache.
for (i = 0; i < CACHE_SIZE; i++)
{
cached[i] = false;
if (cached_stamp[i].frame)
DestroyDrawable (ReleaseDrawable (cached_stamp[i].frame));
cached_stamp[i].frame = 0;
}
}
else
UnlockMutex (flash_mutex);
if (cached_rect.extent.width)
{
STAMP *pStamp;
#define MIN_STRENGTH 4
#define MAX_STRENGTH 6
strength += 2;
if (strength > MAX_STRENGTH)
strength = MIN_STRENGTH;
if (cached[strength - MIN_STRENGTH])
pStamp = &cached_stamp[strength - MIN_STRENGTH];
else
{
pStamp = &cached_stamp[strength - MIN_STRENGTH];
cached[strength - MIN_STRENGTH] = true;
pStamp->frame = CaptureDrawable (
CloneFrame (cached_screen_frame));
pStamp->origin.x = 0;
pStamp->origin.y = 0;
if (strength != 4)
{ // brighten the frame with an additive
DrawMode oldMode;
STAMP s;
int factor;
s.origin.x = 0;
s.origin.y = 0;
s.frame = cached_screen_frame;
factor = (strength - MIN_STRENGTH) * DRAW_FACTOR_1 / 4;
LockMutex (GraphicsLock);
OldContext = SetContext (OffScreenContext);
SetContextFGFrame (pStamp->frame);
SetContextClipRect (NULL);
oldMode = SetContextDrawMode (MAKE_DRAW_MODE (
DRAW_ADDITIVE, factor));
DrawStamp (&s);
SetContextDrawMode (oldMode);
SetContext (OldContext);
UnlockMutex (GraphicsLock);
}
}
LockMutex (GraphicsLock);
OldContext = SetContext (ScreenContext);
SetContextClipRect (&cached_rect);
// flash changed_can't be modified while GraphicSem is held
if (!flash_changed)
DrawStamp (pStamp);
// XXX: Shouldn't we save and restore the original cliprect?
SetContextClipRect (NULL);
SetContext (OldContext);
UnlockMutex (GraphicsLock);
}
FlushGraphics ();
SleepThreadUntil (TimeIn + WaitTime);
TimeIn = GetTimeCounter ();
} }
// Clear cache
{
if (cached_screen_frame)
DestroyDrawable (ReleaseDrawable (cached_screen_frame));
for (i = 0; i < CACHE_SIZE; i++)
{
if(cached_stamp[i].frame)
DestroyDrawable (ReleaseDrawable (cached_stamp[i].frame));
}
}
LockMutex (flash_mutex);
flash_task = 0;
UnlockMutex (flash_mutex);
FinishTask (task); FinishTask (task);
return 0; return 0;
} }
// Pre: the caller holds the GraphicsLock
void void
SetFlashRect (RECT *pRect) SetFlashRect (const RECT *pRect)
{ {
RECT clip_r = {{0, 0}, {0, 0}}; RECT clip_r = {{0, 0}, {0, 0}};
RECT temp_r, flash_rect1, old_r; RECT temp_r;
CONTEXT OldContext;
int create_flash = 0;
if (!flash_mutex) if (!flash_mutex)
flash_mutex = CreateMutex ("FlashRect Lock", flash_mutex = CreateMutex ("FlashRect Lock",
SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO); SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
old_r = flash_rect;
flash_rect1 = flash_rect;
if (pRect != SFR_MENU_3DO && pRect != SFR_MENU_ANY) if (pRect != SFR_MENU_3DO && pRect != SFR_MENU_ANY)
{ {
// The caller specified their own flash area, or NULL (stop flashing).
GetContextClipRect (&clip_r); GetContextClipRect (&clip_r);
OldContext = SetContext (ScreenContext);
} }
else else
{ {
//Don't flash when using the PC menu
if (optWhichMenu == OPT_PC && pRect != SFR_MENU_ANY) if (optWhichMenu == OPT_PC && pRect != SFR_MENU_ANY)
{ {
OldContext = SetContext (ScreenContext); // The player wants PC menus and this flash is not used
// for a PC menu.
// Don't flash.
pRect = 0; pRect = 0;
} }
else else
{ {
OldContext = SetContext (StatusContext); // The player wants 3DO menus, or the flash is used in both
// 3DO and PC mode.
CONTEXT OldContext = SetContext (StatusContext);
GetContextClipRect (&clip_r); GetContextClipRect (&clip_r);
pRect = &temp_r; pRect = &temp_r;
temp_r.corner.x = RADAR_X - clip_r.corner.x; temp_r.corner.x = RADAR_X - clip_r.corner.x;
temp_r.corner.y = RADAR_Y - clip_r.corner.y; temp_r.corner.y = RADAR_Y - clip_r.corner.y;
temp_r.extent.width = RADAR_WIDTH; temp_r.extent.width = RADAR_WIDTH;
temp_r.extent.height = RADAR_HEIGHT; temp_r.extent.height = RADAR_HEIGHT;
SetContext (ScreenContext); SetContext (OldContext);
} }
} }
if (pRect == 0 || pRect->extent.width == 0) // Conclude an old flash task.
if (flashContext != NULL)
{ {
// End the flashing. UnlockMutex (GraphicsLock);
flash_rect1.extent.width = 0; ConcludeTask (flash_task);
if (flash_task) LockMutex (GraphicsLock);
{ flash_task = 0;
UnlockMutex (GraphicsLock);
ConcludeTask (flash_task); Flash_terminate (flashContext);
LockMutex (GraphicsLock); flashContext = 0;
}
}
else
{
flash_rect1 = *pRect;
flash_rect1.corner.x += clip_r.corner.x;
flash_rect1.corner.y += clip_r.corner.y;
create_flash = 1;
}
LockMutex (flash_mutex);
flash_rect = flash_rect1;
if (old_r.extent.width && !rectsEqual (old_r, flash_rect))
{
// 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;
old_s.frame = flash_screen_frame;
DrawStamp (&old_s);
DestroyDrawable (ReleaseDrawable (flash_screen_frame));
flash_screen_frame = 0;
}
else
log_add (log_Debug, "Couldn't locate flash_screen_rect");
}
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));
flash_screen_frame =
CaptureDrawable (LoadDisplayPixmap (&flash_rect, (FRAME)0));
}
flash_changed = 1;
UnlockMutex (flash_mutex);
// we create the thread after the LoadDisplayPixmap()
// so there is no race between the FlushGraphics in flash_task
// and the Enqueue in LoadDisplayPixmap()
if (create_flash && flash_task == 0)
{
flash_task = AssignTask (flash_rect_func, 2048,
"flash rectangle");
} }
SetContext (OldContext); // Start a new flash task.
if (pRect != 0 && pRect->extent.width != 0)
{
flash_rect = *pRect;
flash_rect.corner.x += clip_r.corner.x;
flash_rect.corner.y += clip_r.corner.y;
flashContext = Flash_createHighlight (ScreenContext, &flash_rect);
Flash_setMergeFactors(flashContext, 3, 2, 2);
Flash_setSpeed (flashContext, 0, ONE_SECOND / 16, 0, ONE_SECOND / 16);
Flash_setFrameTime (flashContext, ONE_SECOND / 16);
Flash_start (flashContext);
flash_task = AssignTask (flash_rect_func, 2048, "flash rectangle");
}
}
// Sleep while calling the flash rectangle update when necessary.
void
FlashRectSleepUntil (TimeCount wakeTime)
{
while (GetTimeCounter() < wakeTime)
{
TimeCount flashNextTime = Flash_nextTime (flashContext);
TimeCount nextTime = (flashNextTime < wakeTime) ?
flashNextTime : wakeTime;
SleepThreadUntil (nextTime);
if (nextTime == flashNextTime)
Flash_process (flashContext);
}
}
COUNT updateFlashRectRecursion = 0;
// XXX This is necessary at least because DMS_AddEscortShip() calls
// DrawRaceStrings() in an UpdateFlashRect block, which calls
// ClearSISRect(), which calls DrawMenuStateStrings(), which starts its own
// UpdateFlashRect block. This should probably be cleaned up.
// GraphicsLock must be unlocked.
void
PreUpdateFlashRect (void)
{
if (flash_task)
{
updateFlashRectRecursion++;
if (updateFlashRectRecursion > 1)
return;
LockMutex (flash_mutex);
Flash_pause (flashContext);
// We need to actually pause, as the flash update function
// is called from another thread.
Flash_preUpdate (flashContext);
UnlockMutex (flash_mutex);
}
}
// GraphicsLock must be unlocked.
void
PostUpdateFlashRect (void)
{
if (flash_task)
{
updateFlashRectRecursion--;
if (updateFlashRectRecursion > 0)
return;
LockMutex (flash_mutex);
Flash_postUpdate (flashContext);
Flash_continue (flashContext);
UnlockMutex (flash_mutex);
}
}
// Because the situation occurs a lot where the GraphicsLock is already
// locked, we add this function.
void
PreUpdateFlashRectLocked (void)
{
UnlockMutex (GraphicsLock);
PreUpdateFlashRect ();
LockMutex (GraphicsLock);
}
// Because the situation occurs a lot where the GraphicsLock is already
// locked, we add this function.
void
PostUpdateFlashRectLocked (void)
{
UnlockMutex (GraphicsLock);
PostUpdateFlashRect ();
LockMutex (GraphicsLock);
} }
+5 -1
View File
@@ -181,7 +181,11 @@ extern void RepairSISBorder (void);
extern void InitSISContexts (void); extern void InitSISContexts (void);
extern void DrawSISFrame (void); extern void DrawSISFrame (void);
extern void ClearSISRect (BYTE ClearFlags); extern void ClearSISRect (BYTE ClearFlags);
extern void SetFlashRect (RECT *pRect); extern void SetFlashRect (const RECT *pRect);
extern void PreUpdateFlashRect (void);
extern void PostUpdateFlashRect (void);
extern void PreUpdateFlashRectLocked (void);
extern void PostUpdateFlashRectLocked (void);
#define SFR_MENU_3DO ((RECT*)~0L) #define SFR_MENU_3DO ((RECT*)~0L)
#define SFR_MENU_ANY ((RECT*)~1L) #define SFR_MENU_ANY ((RECT*)~1L)
extern void DrawHyperCoords (POINT puniverse); extern void DrawHyperCoords (POINT puniverse);