Game clock task retired; clock advances via a tick function and the game events are handled immediately

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@3286 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
avolkov
2009-11-07 06:05:45 +00:00
parent d18773e737
commit 60b9df5ba6
17 changed files with 165 additions and 242 deletions
+5 -7
View File
@@ -313,9 +313,11 @@ DoBattle (BATTLE_STATE *bs)
SetTransitionSource (&r); SetTransitionSource (&r);
} }
BatchGraphics (); BatchGraphics ();
if ((LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) &&
!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) // Call the callback function, if set
SeedUniverse (); if (bs->frame_cb)
bs->frame_cb ();
RedrawQueue (TRUE); RedrawQueue (TRUE);
if (bs->first_time) if (bs->first_time)
@@ -331,10 +333,6 @@ DoBattle (BATTLE_STATE *bs)
return FALSE; return FALSE;
} }
// Call the callback function, if set
if (bs->frame_cb)
bs->frame_cb ();
battle_speed = HIBYTE (nth_frame); battle_speed = HIBYTE (nth_frame);
if (battle_speed == (BYTE)~0) if (battle_speed == (BYTE)~0)
{ // maximum speed, nothing rendered at all { // maximum speed, nothing rendered at all
+2 -1
View File
@@ -27,7 +27,8 @@ typedef DWORD BattleFrameCounter;
// For NUM_SIDES // For NUM_SIDES
// The callback function is called on every battle frame // The callback function is called on every battle frame
// with GraphicsLock *not* held // with GraphicsLock held, just before the display queue
// is drawn
typedef void (BattleFrameCallback) (void); typedef void (BattleFrameCallback) (void);
typedef struct battlestate_struct { typedef struct battlestate_struct {
+109 -121
View File
@@ -32,8 +32,11 @@
// and is hard-coded to the original 24 fps // and is hard-coded to the original 24 fps
#define CLOCK_BASE_FRAMERATE 24 #define CLOCK_BASE_FRAMERATE 24
static int clock_task_func(void* data); // WARNING: Most of clock functions are only meant to be called by the
// Starcon2Main thread! If you need access from other threads, examine
// the locking system!
// XXX: This mutex is only necessary because debugging functions
// may access the clock and event data from a different thread
static Mutex clock_mutex; static Mutex clock_mutex;
static BOOLEAN static BOOLEAN
@@ -58,75 +61,51 @@ DaysInMonth (COUNT month, COUNT year)
return days_in_month[month - 1]; return days_in_month[month - 1];
} }
static int static void
clock_task_func(void* data) nextClockDay (void)
{ {
Task task = (Task) data; ++GLOBAL (GameClock.day_index);
if (GLOBAL (GameClock.day_index) > DaysInMonth (
while (GLOBAL (GameClock).day_in_ticks == 0 && !Task_ReadState (task, TASK_EXIT)) GLOBAL (GameClock.month_index),
TaskSwitch (); GLOBAL (GameClock.year_index)))
while (!Task_ReadState (task, TASK_EXIT))
{ {
DWORD TimeIn; GLOBAL (GameClock.day_index) = 1;
++GLOBAL (GameClock.month_index);
/* use semaphore so that time passage if (GLOBAL (GameClock.month_index) > 12)
* can be halted. (e.g. during battle {
* or communications) GLOBAL (GameClock.month_index) = 1;
*/ ++GLOBAL (GameClock.year_index);
SetSemaphore (GLOBAL (GameClock.clock_sem));
TimeIn = GetTimeCounter ();
if (GLOBAL (GameClock).tick_count <= 0
&& (GLOBAL (GameClock).tick_count = GLOBAL (GameClock).day_in_ticks) > 0)
{
/* next day -- move the calendar */
if (++GLOBAL (GameClock).day_index > DaysInMonth (
GLOBAL (GameClock).month_index,
GLOBAL (GameClock).year_index))
{
GLOBAL (GameClock).day_index = 1;
if (++GLOBAL (GameClock).month_index > 12)
{
GLOBAL (GameClock).month_index = 1;
++GLOBAL (GameClock).year_index;
}
}
LockMutex (GraphicsLock);
DrawStatusMessage (NULL);
{
HEVENT hEvent;
while ((hEvent = GetHeadEvent ()))
{
EVENT *EventPtr;
LockEvent (hEvent, &EventPtr);
if (GLOBAL (GameClock).day_index != EventPtr->day_index
|| GLOBAL (GameClock).month_index != EventPtr->month_index
|| GLOBAL (GameClock).year_index != EventPtr->year_index)
{
UnlockEvent (hEvent);
break;
}
RemoveEvent (hEvent);
EventHandler (EventPtr->func_index);
UnlockEvent (hEvent);
FreeEvent (hEvent);
}
}
UnlockMutex (GraphicsLock);
} }
ClearSemaphore (GLOBAL (GameClock.clock_sem));
SleepThreadUntil (TimeIn + ONE_SECOND / 120);
} }
FinishTask (task);
return(0); // update the date on screen
DrawStatusMessage (NULL);
}
static void
processClockDayEvents (void)
{
HEVENT hEvent;
while ((hEvent = GetHeadEvent ()))
{
EVENT *EventPtr;
LockEvent (hEvent, &EventPtr);
if (GLOBAL (GameClock.day_index) != EventPtr->day_index
|| GLOBAL (GameClock.month_index) != EventPtr->month_index
|| GLOBAL (GameClock.year_index) != EventPtr->year_index)
{
UnlockEvent (hEvent);
break;
}
RemoveEvent (hEvent);
EventHandler (EventPtr->func_index);
UnlockEvent (hEvent);
FreeEvent (hEvent);
}
} }
BOOLEAN BOOLEAN
@@ -138,12 +117,8 @@ InitGameClock (void)
GLOBAL (GameClock.month_index) = 2; GLOBAL (GameClock.month_index) = 2;
GLOBAL (GameClock.day_index) = 17; GLOBAL (GameClock.day_index) = 17;
GLOBAL (GameClock.year_index) = START_YEAR; /* Feb 17, START_YEAR */ GLOBAL (GameClock.year_index) = START_YEAR; /* Feb 17, START_YEAR */
GLOBAL (GameClock).tick_count = GLOBAL (GameClock).day_in_ticks = 0; GLOBAL (GameClock.tick_count) = 0;
SuspendGameClock (); GLOBAL (GameClock.day_in_ticks) = 0;
if ((GLOBAL (GameClock.clock_task) =
AssignTask (clock_task_func, 2048,
"game clock")) == 0)
return (FALSE);
return (TRUE); return (TRUE);
} }
@@ -151,14 +126,6 @@ InitGameClock (void)
BOOLEAN BOOLEAN
UninitGameClock (void) UninitGameClock (void)
{ {
if (GLOBAL (GameClock.clock_task))
{
ResumeGameClock ();
ConcludeTask (GLOBAL (GameClock.clock_task));
GLOBAL (GameClock.clock_task) = 0;
}
DestroyMutex (clock_mutex); DestroyMutex (clock_mutex);
clock_mutex = NULL; clock_mutex = NULL;
@@ -167,52 +134,43 @@ UninitGameClock (void)
return (TRUE); return (TRUE);
} }
// For debugging use only
void void
SuspendGameClock (void) LockGameClock (void)
{ {
if (!clock_mutex) // Block the GameClockTick() for executing
{ if (clock_mutex)
log_add (log_Fatal, "BUG: " LockMutex (clock_mutex);
"Attempted to suspend non-existent game clock");
#ifdef DEBUG
explode ();
#endif
return;
}
LockMutex (clock_mutex);
if (GameClockRunning ())
{
SetSemaphore (GLOBAL (GameClock.clock_sem));
GLOBAL (GameClock.TimeCounter) = 0;
}
UnlockMutex (clock_mutex);
} }
// For debugging use only
void void
ResumeGameClock (void) UnlockGameClock (void)
{ {
if (!clock_mutex) if (clock_mutex)
{ UnlockMutex (clock_mutex);
log_add (log_Fatal, "BUG: "
"Attempted to resume non-existent game clock\n");
#ifdef DEBUG
explode ();
#endif
return;
}
LockMutex (clock_mutex);
if (!GameClockRunning ())
{
GLOBAL (GameClock.TimeCounter) = GetTimeCounter ();
ClearSemaphore (GLOBAL (GameClock.clock_sem));
}
UnlockMutex (clock_mutex);
} }
// For debugging use only
BOOLEAN BOOLEAN
GameClockRunning (void) GameClockRunning (void)
{ {
return ((BOOLEAN)(GLOBAL (GameClock.TimeCounter) != 0)); SIZE prev_tick, cur_tick;
if (!clock_mutex)
return FALSE;
LockMutex (clock_mutex);
prev_tick = GLOBAL (GameClock.tick_count);
UnlockMutex (clock_mutex);
SleepThread (ONE_SECOND / 5);
LockMutex (clock_mutex);
cur_tick = GLOBAL (GameClock.tick_count);
UnlockMutex (clock_mutex);
return cur_tick != prev_tick;
} }
void void
@@ -220,7 +178,6 @@ SetGameClockRate (COUNT seconds_per_day)
{ {
SIZE new_day_in_ticks, new_tick_count; SIZE new_day_in_ticks, new_tick_count;
SetSemaphore (GLOBAL (GameClock.clock_sem));
new_day_in_ticks = (SIZE)(seconds_per_day * CLOCK_BASE_FRAMERATE); new_day_in_ticks = (SIZE)(seconds_per_day * CLOCK_BASE_FRAMERATE);
if (GLOBAL (GameClock.day_in_ticks) == 0) if (GLOBAL (GameClock.day_in_ticks) == 0)
new_tick_count = new_day_in_ticks; new_tick_count = new_day_in_ticks;
@@ -231,7 +188,6 @@ SetGameClockRate (COUNT seconds_per_day)
new_tick_count = 1; new_tick_count = 1;
GLOBAL (GameClock.day_in_ticks) = new_day_in_ticks; GLOBAL (GameClock.day_in_ticks) = new_day_in_ticks;
GLOBAL (GameClock.tick_count) = new_tick_count; GLOBAL (GameClock.tick_count) = new_tick_count;
ClearSemaphore (GLOBAL (GameClock.clock_sem));
} }
BOOLEAN BOOLEAN
@@ -324,9 +280,41 @@ AddEvent (EVENT_TYPE type, COUNT month_index, COUNT day_index, COUNT
return (0); return (0);
} }
SIZE // This function must be called with GraphicsLock held.
ClockTick (void) void
GameClockTick (void)
{ {
return (--GLOBAL (GameClock.tick_count)); // XXX: This mutex is only necessary because debugging functions
// may access the clock and event data from a different thread
LockMutex (clock_mutex);
--GLOBAL (GameClock.tick_count);
if (GLOBAL (GameClock.tick_count) <= 0)
{ // next day -- move the calendar
GLOBAL (GameClock.tick_count) = GLOBAL (GameClock.day_in_ticks);
// Do not do anything until the clock is inited
if (GLOBAL (GameClock.day_in_ticks) > 0)
{
nextClockDay ();
processClockDayEvents ();
}
}
UnlockMutex (clock_mutex);
} }
// This function must be called with GraphicsLock held.
void
MoveGameClockDays (COUNT days)
{
// XXX: This should theoretically hold the clock_mutex, but if
// someone manages to hit the debug button while this function
// runs, it's their own fault :-P
for ( ; days > 0; --days)
{
nextClockDay ();
processClockDayEvents ();
}
GLOBAL (GameClock.tick_count) = GLOBAL (GameClock.day_in_ticks);
}
+17 -8
View File
@@ -34,9 +34,6 @@ typedef struct
BYTE day_index, month_index; BYTE day_index, month_index;
COUNT year_index; COUNT year_index;
SIZE tick_count, day_in_ticks; SIZE tick_count, day_in_ticks;
Semaphore clock_sem;
Task clock_task;
DWORD TimeCounter;
QUEUE event_q; QUEUE event_q;
/* Queue element is EVENT */ /* Queue element is EVENT */
@@ -74,22 +71,34 @@ typedef enum
#define ForAllEvents(callback, arg) ForAllLinks(&GLOBAL (GameClock.event_q), \ #define ForAllEvents(callback, arg) ForAllLinks(&GLOBAL (GameClock.event_q), \
(void (*)(LINK *, void *)) (callback), (arg)) (void (*)(LINK *, void *)) (callback), (arg))
/* rates are in seconds per game day */ // Rates are in seconds per game day
#define HYPERSPACE_CLOCK_RATE 5 #define HYPERSPACE_CLOCK_RATE 5
// XXX: the IP rate is based on 24 ticks/second (see SetGameClockRate),
// however, IP runs at 30 fps right now. So in reality, the IP clock
// rate is closer to 23 seconds per game day. The clock is faster, but
// the flagship also moves faster.
#define INTERPLANETARY_CLOCK_RATE 30 #define INTERPLANETARY_CLOCK_RATE 30
extern BOOLEAN InitGameClock (void); extern BOOLEAN InitGameClock (void);
extern BOOLEAN UninitGameClock (void); extern BOOLEAN UninitGameClock (void);
extern void SuspendGameClock (void);
extern void ResumeGameClock (void);
extern BOOLEAN GameClockRunning (void);
extern void SetGameClockRate (COUNT seconds_per_day); extern void SetGameClockRate (COUNT seconds_per_day);
extern BOOLEAN ValidateEvent (EVENT_TYPE type, COUNT *pmonth_index, extern BOOLEAN ValidateEvent (EVENT_TYPE type, COUNT *pmonth_index,
COUNT *pday_index, COUNT *pyear_index); COUNT *pday_index, COUNT *pyear_index);
extern HEVENT AddEvent (EVENT_TYPE type, COUNT month_index, COUNT extern HEVENT AddEvent (EVENT_TYPE type, COUNT month_index, COUNT
day_index, COUNT year_index, BYTE func_index); day_index, COUNT year_index, BYTE func_index);
extern void EventHandler (BYTE selector); extern void EventHandler (BYTE selector);
extern SIZE ClockTick (void); extern void GameClockTick (void);
extern void MoveGameClockDays (COUNT days);
// The lock/unlock/running functions are for debugging use only
// Locking will block the GameClockTick() function and thus
// the thread moving the clock.
extern void LockGameClock (void);
extern void UnlockGameClock (void);
// A weak indicator of the clock moving. Suitable for debugging,
// but not much else
extern BOOLEAN GameClockRunning (void);
#endif /* _CLOCK_H */ #endif /* _CLOCK_H */
-8
View File
@@ -83,10 +83,6 @@ DoConfirmExit (void)
{ {
BOOLEAN result; BOOLEAN result;
if (LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE &&
LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE &&
!(LastActivity & CHECK_RESTART))
SuspendGameClock ();
if (CommData.ConversationPhrases && PlayingTrack ()) if (CommData.ConversationPhrases && PlayingTrack ())
PauseTrack (); PauseTrack ();
@@ -174,10 +170,6 @@ DoConfirmExit (void)
} }
UnlockMutex (GraphicsLock); UnlockMutex (GraphicsLock);
if (LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE &&
LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE &&
!(LastActivity & CHECK_RESTART))
ResumeGameClock ();
if (CommData.ConversationPhrases && PlayingTrack ()) if (CommData.ConversationPhrases && PlayingTrack ())
ResumeTrack (); ResumeTrack ();
-6
View File
@@ -418,12 +418,6 @@ InitGlobData (void)
GLOBAL (glob_flags) = (BYTE)i; GLOBAL (glob_flags) = (BYTE)i;
GLOBAL (DisplayArray) = DisplayArray; GLOBAL (DisplayArray) = DisplayArray;
// The clock semaphore was initially initialized as '1'
// but it is always cleared before set, so it toggled between
// 2 and 1, which doesn't actually do anything.
GLOBAL (GameClock.clock_sem) =
CreateSemaphore(0, "Clock", SYNC_CLASS_TOPLEVEL);
} }
-8
View File
@@ -357,10 +357,6 @@ LoadHyperspace (void)
BOOLEAN BOOLEAN
FreeHyperspace (void) FreeHyperspace (void)
{ {
UnlockMutex (GraphicsLock);
SuspendGameClock ();
LockMutex (GraphicsLock);
{ {
FRAME F; FRAME F;
@@ -1337,8 +1333,6 @@ SeedUniverse (void)
HELEMENT hHyperSpaceElement; HELEMENT hHyperSpaceElement;
ELEMENT *HyperSpaceElementPtr; ELEMENT *HyperSpaceElementPtr;
ClockTick ();
universe.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)); universe.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x));
universe.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); universe.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y));
@@ -1613,7 +1607,6 @@ UnbatchGraphics ();
OldColor = SetContextBackGroundColor (BLACK_COLOR); OldColor = SetContextBackGroundColor (BLACK_COLOR);
UnlockMutex (GraphicsLock); UnlockMutex (GraphicsLock);
SuspendGameClock ();
memset (&MenuState, 0, sizeof (MenuState)); memset (&MenuState, 0, sizeof (MenuState));
MenuState.InputFunc = DoFlagshipCommands; MenuState.InputFunc = DoFlagshipCommands;
@@ -1638,7 +1631,6 @@ UnbatchGraphics ();
ClearSISRect (CLEAR_SIS_RADAR); ClearSISRect (CLEAR_SIS_RADAR);
UnlockMutex (GraphicsLock); UnlockMutex (GraphicsLock);
WaitForNoInput (ONE_SECOND / 2); WaitForNoInput (ONE_SECOND / 2);
ResumeGameClock ();
LockMutex (GraphicsLock); LockMutex (GraphicsLock);
} }
+1 -9
View File
@@ -371,7 +371,7 @@ LoadClockState (CLOCK_STATE *ClockPtr, DECODE_REF fh)
cread_16 (fh, &ClockPtr->day_in_ticks); cread_16 (fh, &ClockPtr->day_in_ticks);
cread_ptr (fh); /* not loading ptr; Semaphore clock_sem */ cread_ptr (fh); /* not loading ptr; Semaphore clock_sem */
cread_ptr (fh); /* not loading ptr; Task clock_task */ cread_ptr (fh); /* not loading ptr; Task clock_task */
cread_32 (fh, &ClockPtr->TimeCounter); /* theoretically useless */ cread_32 (fh, NULL); /* not loading; DWORD TimeCounter */
DummyLoadQueue (&ClockPtr->event_q, fh); DummyLoadQueue (&ClockPtr->event_q, fh);
} }
@@ -566,14 +566,6 @@ LoadGame (COUNT which_game, SUMMARY_DESC *SummPtr)
NextActivity = GLOBAL (CurrentActivity); NextActivity = GLOBAL (CurrentActivity);
GLOBAL (CurrentActivity) = Activity; GLOBAL (CurrentActivity) = Activity;
// It shouldn't be possible to ever save with TimeCounter != 0
// But if it does happen, it needs to be reset to 0, since on load
// the clock semaphore is gauranteed to be 0
if (GLOBAL (GameClock.TimeCounter) != 0)
log_add (log_Warning, "Warning: Game clock wasn't stopped during "
"save, Savegame may be corrupt!\n");
GLOBAL (GameClock.TimeCounter) = 0;
LoadRaceQueue (fh, &GLOBAL (avail_race_q)); LoadRaceQueue (fh, &GLOBAL (avail_race_q));
// START_INTERPLANETARY is only set when saving from Homeworld // START_INTERPLANETARY is only set when saving from Homeworld
// encounter screen. When the game is loaded, GENERATE_ORBITAL will // encounter screen. When the game is loaded, GENERATE_ORBITAL will
+3 -10
View File
@@ -67,19 +67,12 @@ ZapToUrquanEncounter (void)
{ {
#define LOST_DAYS 15 #define LOST_DAYS 15
COUNT i;
BYTE black_buf[] = {FadeAllToBlack}; BYTE black_buf[] = {FadeAllToBlack};
SleepThreadUntil (XFormColorMap ((COLORMAPPTR)black_buf, ONE_SECOND * 2)); SleepThreadUntil (XFormColorMap ((COLORMAPPTR)black_buf, ONE_SECOND * 2));
for (i = 0; i < LOST_DAYS; ++i) LockMutex (GraphicsLock);
{ MoveGameClockDays (LOST_DAYS);
while (ClockTick () > 0) UnlockMutex (GraphicsLock);
;
ResumeGameClock ();
SleepThread (ONE_SECOND / 60);
SuspendGameClock ();
}
} }
GLOBAL (CurrentActivity) = MAKE_WORD (IN_HYPERSPACE, 0) | START_ENCOUNTER; GLOBAL (CurrentActivity) = MAKE_WORD (IN_HYPERSPACE, 0) | START_ENCOUNTER;
-1
View File
@@ -1805,7 +1805,6 @@ DoFlagshipCommands (MENU_STATE *pMS)
if (pMS->Initialized <= 1) if (pMS->Initialized <= 1)
{ {
pMS->Initialized = 1; pMS->Initialized = 1;
ResumeGameClock ();
} }
else if (pMS->flash_task) else if (pMS->flash_task)
{ {
+3 -6
View File
@@ -854,8 +854,6 @@ ProcessShipControls (void)
COUNT index; COUNT index;
SIZE delta_x, delta_y; SIZE delta_x, delta_y;
ClockTick ();
if (CurrentInputState.key[PlayerControls[0]][KEY_UP]) if (CurrentInputState.key[PlayerControls[0]][KEY_UP])
delta_y = -1; delta_y = -1;
else else
@@ -1165,7 +1163,10 @@ IP_frame (void)
} }
if (!(draw_sys_flags & DRAW_REFRESH)) if (!(draw_sys_flags & DRAW_REFRESH))
{
GameClockTick ();
ProcessShipControls (); ProcessShipControls ();
}
UndrawShip (); UndrawShip ();
if (pSolarSysState->MenuState.Initialized != 1) if (pSolarSysState->MenuState.Initialized != 1)
{ {
@@ -1270,8 +1271,6 @@ IP_frame (void)
} }
else else
{ {
SuspendGameClock ();
LockMutex (GraphicsLock); LockMutex (GraphicsLock);
DrawStatusMessage (NULL); DrawStatusMessage (NULL);
if (LastActivity == CHECK_LOAD) if (LastActivity == CHECK_LOAD)
@@ -1403,7 +1402,6 @@ StartGroups:
} }
} }
ResumeGameClock ();
SetGameClockRate (INTERPLANETARY_CLOCK_RATE); SetGameClockRate (INTERPLANETARY_CLOCK_RATE);
} }
} }
@@ -1411,7 +1409,6 @@ StartGroups:
{ {
if (pSolarSysState->MenuState.flash_task) if (pSolarSysState->MenuState.flash_task)
{ {
SuspendGameClock ();
FreeSolarSys (); FreeSolarSys ();
if (pSolarSysState->pOrbitalDesc->pPrevDesc != if (pSolarSysState->pOrbitalDesc->pPrevDesc !=
+1 -1
View File
@@ -341,7 +341,7 @@ SaveClockState (const CLOCK_STATE *ClockPtr, DECODE_REF fh)
cwrite_16 (fh, ClockPtr->day_in_ticks); cwrite_16 (fh, ClockPtr->day_in_ticks);
cwrite_ptr (fh); /* useless ptr; Semaphore clock_sem */ cwrite_ptr (fh); /* useless ptr; Semaphore clock_sem */
cwrite_ptr (fh); /* useless ptr; Task clock_task */ cwrite_ptr (fh); /* useless ptr; Task clock_task */
cwrite_32 (fh, ClockPtr->TimeCounter); /* theoretically useless */ cwrite_32 (fh, 0); /* useless value; DWORD TimeCounter */
DummySaveQueue (&ClockPtr->event_q, fh); DummySaveQueue (&ClockPtr->event_q, fh);
} }
-5
View File
@@ -213,11 +213,6 @@ ship_preprocess (ELEMENT *ElementPtr)
InitIntersectStartPoint (ElementPtr); InitIntersectStartPoint (ElementPtr);
InitIntersectEndPoint (ElementPtr); InitIntersectEndPoint (ElementPtr);
UnlockMutex (GraphicsLock);
ResumeGameClock ();
SetGameClockRate (HYPERSPACE_CLOCK_RATE);
LockMutex (GraphicsLock);
if (hyper_transition (ElementPtr)) if (hyper_transition (ElementPtr))
return; return;
} }
+3 -10
View File
@@ -443,20 +443,13 @@ static void
DoTimePassage (void) DoTimePassage (void)
{ {
#define LOST_DAYS 14 #define LOST_DAYS 14
COUNT i;
BYTE clut_buf[1]; BYTE clut_buf[1];
clut_buf[0] = FadeAllToBlack; clut_buf[0] = FadeAllToBlack;
SleepThreadUntil (XFormColorMap ((COLORMAPPTR)clut_buf, ONE_SECOND * 2)); SleepThreadUntil (XFormColorMap ((COLORMAPPTR)clut_buf, ONE_SECOND * 2));
for (i = 0; i < LOST_DAYS; ++i) LockMutex (GraphicsLock);
{ MoveGameClockDays (LOST_DAYS);
while (ClockTick () > 0) UnlockMutex (GraphicsLock);
;
ResumeGameClock ();
SleepThread (ONE_SECOND / 60);
SuspendGameClock ();
}
} }
void void
+10 -7
View File
@@ -60,8 +60,7 @@ arilou_gate_task(void *data)
counter = GET_GAME_STATE (ARILOU_SPACE_COUNTER); counter = GET_GAME_STATE (ARILOU_SPACE_COUNTER);
while (!Task_ReadState (task, TASK_EXIT)) while (!Task_ReadState (task, TASK_EXIT))
{ {
SetSemaphore (GLOBAL (GameClock.clock_sem)); LockGameClock ();
if (GET_GAME_STATE (ARILOU_SPACE) == OPENING) if (GET_GAME_STATE (ARILOU_SPACE) == OPENING)
{ {
if (++counter == 10) if (++counter == 10)
@@ -72,12 +71,12 @@ arilou_gate_task(void *data)
if (counter-- == 0) if (counter-- == 0)
counter = 0; counter = 0;
} }
UnlockGameClock ();
LockMutex (GraphicsLock); LockMutex (GraphicsLock);
SET_GAME_STATE (ARILOU_SPACE_COUNTER, counter); SET_GAME_STATE (ARILOU_SPACE_COUNTER, counter);
UnlockMutex (GraphicsLock); UnlockMutex (GraphicsLock);
ClearSemaphore (GLOBAL (GameClock.clock_sem));
SleepThreadUntil (TimeIn + BATTLE_FRAME_RATE); SleepThreadUntil (TimeIn + BATTLE_FRAME_RATE);
TimeIn = GetTimeCounter (); TimeIn = GetTimeCounter ();
} }
@@ -86,12 +85,17 @@ arilou_gate_task(void *data)
return 0; return 0;
} }
// Battle frame callback function.
// Called with GraphicsLock held
static void static void
on_battle_frame (void) on_battle_frame (void)
{ {
LockMutex (GraphicsLock); GameClockTick ();
if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)))
SeedUniverse ();
DrawAutoPilotMessage (FALSE); DrawAutoPilotMessage (FALSE);
UnlockMutex (GraphicsLock);
} }
static void static void
@@ -212,8 +216,6 @@ while (--ac > 0)
do do
{ {
SuspendGameClock ();
#ifdef DEBUG #ifdef DEBUG
if (debugHook != NULL) if (debugHook != NULL)
{ {
@@ -278,6 +280,7 @@ while (--ac > 0)
TaskSwitch (); TaskSwitch ();
DrawAutoPilotMessage (TRUE); DrawAutoPilotMessage (TRUE);
SetGameClockRate (HYPERSPACE_CLOCK_RATE);
Battle (&on_battle_frame); Battle (&on_battle_frame);
if (ArilouTask) if (ArilouTask)
Task_SetState (ArilouTask, TASK_EXIT); Task_SetState (ArilouTask, TASK_EXIT);
+11 -22
View File
@@ -138,7 +138,10 @@ forwardToNextEvent (BOOLEAN skipHEE)
if (!GameClockRunning ()) if (!GameClockRunning ())
return; return;
SuspendGameClock (); // Must hold GraphicsLock for MoveGameClockDays()
// Must acquire GraphicsLock *before* the game clock lock
LockMutex (GraphicsLock);
LockGameClock ();
done = !skipHEE; done = !skipHEE;
do { do {
@@ -161,16 +164,12 @@ forwardToNextEvent (BOOLEAN skipHEE)
GLOBAL (GameClock.day_index) >= day)))) GLOBAL (GameClock.day_index) >= day))))
break; break;
while (ClockTick () > 0) MoveGameClockDays (1);
;
ResumeGameClock ();
SleepThread (ONE_SECOND / 60);
SuspendGameClock ();
} }
} while (!done); } while (!done);
ResumeGameClock (); UnlockGameClock ();
UnlockMutex (GraphicsLock);
} }
const char * const char *
@@ -239,15 +238,9 @@ dumpEvent (FILE *out, const EVENT *eventPtr)
void void
dumpEvents (FILE *out) dumpEvents (FILE *out)
{ {
BOOLEAN restartClock = FALSE; LockGameClock ();
if (GameClockRunning ()) {
SuspendGameClock ();
restartClock = TRUE;
}
ForAllEvents (dumpEventCallback, out); ForAllEvents (dumpEventCallback, out);
if (restartClock) UnlockGameClock ();
ResumeGameClock ();
} }
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
@@ -592,7 +585,6 @@ forAllMoons (STAR_DESC *star, SOLARSYS_STATE *system, PLANET_DESC *planet,
void void
UniverseRecurse (UniverseRecurseArg *universeRecurseArg) UniverseRecurse (UniverseRecurseArg *universeRecurseArg)
{ {
BOOLEAN clockRunning;
ACTIVITY savedActivity; ACTIVITY savedActivity;
if (universeRecurseArg->systemFuncPre == NULL if (universeRecurseArg->systemFuncPre == NULL
@@ -602,9 +594,7 @@ UniverseRecurse (UniverseRecurseArg *universeRecurseArg)
&& universeRecurseArg->moonFunc == NULL) && universeRecurseArg->moonFunc == NULL)
return; return;
clockRunning = GameClockRunning (); LockGameClock ();
if (clockRunning)
SuspendGameClock ();
//TFB_DEBUG_HALT = 1; //TFB_DEBUG_HALT = 1;
savedActivity = GLOBAL (CurrentActivity); savedActivity = GLOBAL (CurrentActivity);
disableInteractivity = TRUE; disableInteractivity = TRUE;
@@ -613,8 +603,7 @@ UniverseRecurse (UniverseRecurseArg *universeRecurseArg)
disableInteractivity = FALSE; disableInteractivity = FALSE;
GLOBAL (CurrentActivity) = savedActivity; GLOBAL (CurrentActivity) = savedActivity;
if (clockRunning) UnlockGameClock ();
ResumeGameClock ();
} }
static void static void
-12
View File
@@ -161,9 +161,6 @@ PauseGame (void)
GLOBAL (CurrentActivity) |= CHECK_PAUSE; GLOBAL (CurrentActivity) |= CHECK_PAUSE;
if (LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE &&
LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE)
SuspendGameClock ();
if (CommData.ConversationPhrases && PlayingTrack ()) if (CommData.ConversationPhrases && PlayingTrack ())
PauseTrack (); PauseTrack ();
@@ -221,9 +218,6 @@ PauseGame (void)
WaitForNoInput (ONE_SECOND / 4); WaitForNoInput (ONE_SECOND / 4);
FlushInput (); FlushInput ();
if (LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE &&
LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE)
ResumeGameClock ();
if (CommData.ConversationPhrases && PlayingTrack ()) if (CommData.ConversationPhrases && PlayingTrack ())
ResumeTrack (); ResumeTrack ();
@@ -263,9 +257,6 @@ SleepGame (void)
log_add (log_Debug, "Game is going to sleep"); log_add (log_Debug, "Game is going to sleep");
if (LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE &&
LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE)
SuspendGameClock ();
if (CommData.ConversationPhrases && PlayingTrack ()) if (CommData.ConversationPhrases && PlayingTrack ())
PauseTrack (); PauseTrack ();
PauseMusic (); PauseMusic ();
@@ -282,9 +273,6 @@ SleepGame (void)
ResumeMusic (); ResumeMusic ();
if (LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE &&
LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE)
ResumeGameClock ();
if (CommData.ConversationPhrases && PlayingTrack ()) if (CommData.ConversationPhrases && PlayingTrack ())
ResumeTrack (); ResumeTrack ();