diff options
Diffstat (limited to 'src/uqm/util.c')
-rw-r--r-- | src/uqm/util.c | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/src/uqm/util.c b/src/uqm/util.c new file mode 100644 index 0000000..aee73a6 --- /dev/null +++ b/src/uqm/util.c @@ -0,0 +1,312 @@ +//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 "controls.h" +#include "util.h" +#include "setup.h" +#include "units.h" +#include "settings.h" +#include "libs/inplib.h" +#include "libs/sound/trackplayer.h" +#include "libs/mathlib.h" +#include "libs/log.h" + + +void +DrawStarConBox (RECT *pRect, SIZE BorderWidth, Color TopLeftColor, + Color BottomRightColor, BOOLEAN FillInterior, Color InteriorColor) +{ + RECT locRect; + + if (BorderWidth == 0) + BorderWidth = 2; + else + { + SetContextForeGroundColor (TopLeftColor); + locRect.corner = pRect->corner; + locRect.extent.width = pRect->extent.width; + locRect.extent.height = 1; + DrawFilledRectangle (&locRect); + if (BorderWidth == 2) + { + ++locRect.corner.x; + ++locRect.corner.y; + locRect.extent.width -= 2; + DrawFilledRectangle (&locRect); + } + + locRect.corner = pRect->corner; + locRect.extent.width = 1; + locRect.extent.height = pRect->extent.height; + DrawFilledRectangle (&locRect); + if (BorderWidth == 2) + { + ++locRect.corner.x; + ++locRect.corner.y; + locRect.extent.height -= 2; + DrawFilledRectangle (&locRect); + } + + SetContextForeGroundColor (BottomRightColor); + locRect.corner.x = pRect->corner.x + pRect->extent.width - 1; + locRect.corner.y = pRect->corner.y + 1; + locRect.extent.height = pRect->extent.height - 1; + DrawFilledRectangle (&locRect); + if (BorderWidth == 2) + { + --locRect.corner.x; + ++locRect.corner.y; + locRect.extent.height -= 2; + DrawFilledRectangle (&locRect); + } + + locRect.corner.x = pRect->corner.x; + locRect.extent.width = pRect->extent.width; + locRect.corner.y = pRect->corner.y + pRect->extent.height - 1; + locRect.extent.height = 1; + DrawFilledRectangle (&locRect); + if (BorderWidth == 2) + { + ++locRect.corner.x; + --locRect.corner.y; + locRect.extent.width -= 2; + DrawFilledRectangle (&locRect); + } + } + + if (FillInterior) + { + SetContextForeGroundColor (InteriorColor); + locRect.corner.x = pRect->corner.x + BorderWidth; + locRect.corner.y = pRect->corner.y + BorderWidth; + locRect.extent.width = pRect->extent.width - (BorderWidth << 1); + locRect.extent.height = pRect->extent.height - (BorderWidth << 1); + DrawFilledRectangle (&locRect); + } +} + +DWORD +SeedRandomNumbers (void) +{ + DWORD cur_time; + + cur_time = GetTimeCounter (); + TFB_SeedRandom (cur_time); + + return (cur_time); +} + +STAMP +SaveContextFrame (const RECT *saveRect) +{ + STAMP s; + + if (saveRect) + { // a portion of the context + s.origin = saveRect->corner; + } + else + { // the entire context + s.origin.x = 0; + s.origin.y = 0; + } + + s.frame = CaptureDrawable (CopyContextRect (saveRect)); + + return s; +} + +BOOLEAN +PauseGame (void) +{ + RECT r; + STAMP s; + CONTEXT OldContext; + STAMP saveStamp; + RECT ctxRect; + POINT oldOrigin; + RECT OldRect; + + if (ActivityFrame == 0 + || (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_PAUSE)) + || (LastActivity & (CHECK_LOAD | CHECK_RESTART))) + return (FALSE); + + GLOBAL (CurrentActivity) |= CHECK_PAUSE; + + if (PlayingTrack ()) + PauseTrack (); + + OldContext = SetContext (ScreenContext); + oldOrigin = SetContextOrigin (MAKE_POINT (0, 0)); + GetContextClipRect (&OldRect); + SetContextClipRect (NULL); + + GetContextClipRect (&ctxRect); + GetFrameRect (ActivityFrame, &r); + r.corner.x = (ctxRect.extent.width - r.extent.width) >> 1; + r.corner.y = (ctxRect.extent.height - r.extent.height) >> 1; + saveStamp = SaveContextFrame (&r); + + // TODO: This should draw a localizable text message instead + s.origin = r.corner; + s.frame = ActivityFrame; + SetSystemRect (&r); + DrawStamp (&s); + + FlushGraphics (); + + while (ImmediateInputState.menu[KEY_PAUSE] && GamePaused) + { + BeginInputFrame (); + TaskSwitch (); + } + + while (!ImmediateInputState.menu[KEY_PAUSE] && GamePaused) + { + BeginInputFrame (); + TaskSwitch (); + } + + while (ImmediateInputState.menu[KEY_PAUSE] && GamePaused) + { + BeginInputFrame (); + TaskSwitch (); + } + + GamePaused = FALSE; + + DrawStamp (&saveStamp); + DestroyDrawable (ReleaseDrawable (saveStamp.frame)); + ClearSystemRect (); + + SetContextClipRect (&OldRect); + SetContextOrigin (oldOrigin); + SetContext (OldContext); + + WaitForNoInput (ONE_SECOND / 4, TRUE); + + if (PlayingTrack ()) + ResumeTrack (); + + + TaskSwitch (); + GLOBAL (CurrentActivity) &= ~CHECK_PAUSE; + return (TRUE); +} + +// Waits for a button to be pressed +// Returns TRUE if the wait succeeded (found input) +// FALSE if timed out or game aborted +BOOLEAN +WaitForAnyButtonUntil (BOOLEAN newButton, TimeCount timeOut, + BOOLEAN resetInput) +{ + BOOLEAN buttonPressed; + + if (newButton && !WaitForNoInputUntil (timeOut, FALSE)) + return FALSE; + + buttonPressed = AnyButtonPress (TRUE); + while (!buttonPressed + && (timeOut == WAIT_INFINITE || GetTimeCounter () < timeOut) + && !(GLOBAL (CurrentActivity) & CHECK_ABORT) + && !QuitPosted) + { + SleepThread (ONE_SECOND / 40); + buttonPressed = AnyButtonPress (TRUE); + } + + if (resetInput) + FlushInput (); + + return buttonPressed; +} + +BOOLEAN +WaitForAnyButton (BOOLEAN newButton, TimePeriod duration, BOOLEAN resetInput) +{ + TimeCount timeOut = duration; + if (duration != WAIT_INFINITE) + timeOut += GetTimeCounter (); + return WaitForAnyButtonUntil (newButton, timeOut, resetInput); +} + +// Returns TRUE if the wait succeeded (found no input) +// FALSE if timed out or game aborted +BOOLEAN +WaitForNoInputUntil (TimeCount timeOut, BOOLEAN resetInput) +{ + BOOLEAN buttonPressed; + + buttonPressed = AnyButtonPress (TRUE); + while (buttonPressed + && (timeOut == WAIT_INFINITE || GetTimeCounter () < timeOut) + && !(GLOBAL (CurrentActivity) & CHECK_ABORT) + && !QuitPosted) + { + SleepThread (ONE_SECOND / 40); + buttonPressed = AnyButtonPress (TRUE); + } + + if (resetInput) + FlushInput (); + + return !buttonPressed; +} + +BOOLEAN +WaitForNoInput (TimePeriod duration, BOOLEAN resetInput) +{ + TimeCount timeOut = duration; + if (duration != WAIT_INFINITE) + timeOut += GetTimeCounter (); + return WaitForNoInputUntil (timeOut, resetInput); +} + +// Stops game clock and music thread and minimizes interrupts/cycles +// based on value of global GameActive variable +// See similar sleep state for main thread in uqm.c:main() +void +SleepGame (void) +{ + if (QuitPosted) + return; // Do not sleep the game when already asked to quit + + log_add (log_Debug, "Game is going to sleep"); + + if (PlayingTrack ()) + PauseTrack (); + PauseMusic (); + + + while (!GameActive && !QuitPosted) + SleepThread (ONE_SECOND / 2); + + log_add (log_Debug, "Game is waking up"); + + WaitForNoInput (ONE_SECOND / 10, TRUE); + + ResumeMusic (); + + if (PlayingTrack ()) + ResumeTrack (); + + + TaskSwitch (); +} |