bool CBaseOperThread::ReStart() { if( m_hThread == NULL ) { if( !CreateThread( NULL, 0, EntryPoint, this, CREATE_SUSPENDED )) { return false; } if( ResumeThread( m_hThread ) == -1) { return false; } else { ClearSemaphore(); m_bIsExit = false; return true; } } return false; }
COUNT ActivateStarShip (COUNT which_ship, SIZE state) { HSTARSHIP hStarShip, hNextShip; hStarShip = GetStarShipFromIndex ( &GLOBAL (avail_race_q), which_ship ); if (hStarShip) { switch (state) { case SPHERE_TRACKING: case SPHERE_KNOWN: { EXTENDED_SHIP_FRAGMENTPTR StarShipPtr; StarShipPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hStarShip ); if (state == SPHERE_KNOWN) which_ship = StarShipPtr->ShipInfo.known_strength; else if (StarShipPtr->ShipInfo.actual_strength == 0) { if (!(StarShipPtr->ShipInfo.ship_flags & (GOOD_GUY | BAD_GUY))) which_ship = 0; } else if (StarShipPtr->ShipInfo.known_strength == 0 && StarShipPtr->ShipInfo.actual_strength != (COUNT)~0) { StarShipPtr->ShipInfo.known_strength = 1; StarShipPtr->ShipInfo.known_loc = StarShipPtr->ShipInfo.loc; } UnlockStarShip ( &GLOBAL (avail_race_q), hStarShip ); return (which_ship); } case ESCORT_WORTH: which_ship = 0; case ESCORTING_FLAGSHIP: { COUNT ShipCost[] = { RACE_SHIP_COST }; for (hStarShip = GetHeadLink (&GLOBAL (built_ship_q)); hStarShip; hStarShip = hNextShip) { BYTE ship_type; SHIP_FRAGMENTPTR StarShipPtr; StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (built_ship_q), hStarShip ); hNextShip = _GetSuccLink (StarShipPtr); if (state == ESCORT_WORTH) which_ship += ShipCost[GET_RACE_ID (StarShipPtr)]; else ship_type = GET_RACE_ID (StarShipPtr); UnlockStarShip ( &GLOBAL (built_ship_q), hStarShip ); if (state != ESCORT_WORTH && (COUNT)ship_type == which_ship) return (1); } return (state == ESCORTING_FLAGSHIP ? 0 : which_ship); } case FEASIBILITY_STUDY: return (MAX_BUILT_SHIPS - CountLinks (&GLOBAL (built_ship_q))); default: { SHIP_FRAGMENTPTR StarShipPtr; if (state <= 0) { StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hStarShip ); if (state == CHECK_ALLIANCE) { state = StarShipPtr->ShipInfo.ship_flags & (GOOD_GUY | BAD_GUY); UnlockStarShip ( &GLOBAL (avail_race_q), hStarShip ); return ((COUNT)state); } else if (StarShipPtr->ShipInfo.ship_flags & (GOOD_GUY | BAD_GUY)) { StarShipPtr->ShipInfo.ship_flags &= ~(GOOD_GUY | BAD_GUY); if (state == 0) StarShipPtr->ShipInfo.ship_flags |= GOOD_GUY; else { StarShipPtr->ShipInfo.ship_flags |= BAD_GUY; if (which_ship == ORZ_SHIP) { BOOLEAN ShipRemoved; ShipRemoved = FALSE; for (hStarShip = GetHeadLink ( &GLOBAL (built_ship_q )); hStarShip; hStarShip = hNextShip) { BOOLEAN RemoveShip; SHIP_FRAGMENTPTR StarShipPtr; StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (built_ship_q), hStarShip ); hNextShip = _GetSuccLink (StarShipPtr); RemoveShip = (BOOLEAN)( GET_RACE_ID (StarShipPtr) == ORZ_SHIP ); UnlockStarShip ( &GLOBAL (built_ship_q), hStarShip ); if (RemoveShip) { ShipRemoved = TRUE; RemoveQueue ( &GLOBAL (built_ship_q), hStarShip ); FreeStarShip ( &GLOBAL (built_ship_q), hStarShip ); } } if (ShipRemoved) { SetSemaphore (GraphicsSem); DeltaSISGauges (UNDEFINED_DELTA, UNDEFINED_DELTA, UNDEFINED_DELTA); ClearSemaphore (GraphicsSem); } } } } UnlockStarShip ( &GLOBAL (avail_race_q), hStarShip ); } else { BYTE which_window; COUNT i; which_window = 0; for ( i = 0; i < (COUNT)state && ( hStarShip = CloneShipFragment ( (COUNT)which_ship, (PQUEUE)(&GLOBAL (built_ship_q)), (BYTE) ( ( which_ship == SPATHI_SHIP && GET_GAME_STATE (FOUND_PLUTO_SPATHI) ) == 1 ? 1 : 0 ) ) ); i++ ) { HSTARSHIP hOldShip; RemoveQueue ( &GLOBAL (built_ship_q), hStarShip ); while ((hOldShip = GetStarShipFromIndex ( &GLOBAL (built_ship_q), which_window++ ))) { BYTE win_loc; StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (built_ship_q), hOldShip ); win_loc = GET_GROUP_LOC (StarShipPtr); UnlockStarShip ( &GLOBAL (built_ship_q), hOldShip ); if (which_window <= win_loc) break; } StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (built_ship_q), hStarShip ); SET_GROUP_LOC (StarShipPtr, which_window - 1); if (which_ship == SPATHI_SHIP && GET_GAME_STATE (FOUND_PLUTO_SPATHI) == 1) { OwnStarShip (StarShipPtr, GOOD_GUY, NAME_OFFSET + NUM_CAPTAINS_NAMES); } UnlockStarShip ( &GLOBAL (built_ship_q), hStarShip ); InsertQueue ( &GLOBAL (built_ship_q), hStarShip, hOldShip ); } SetSemaphore (GraphicsSem); DeltaSISGauges (UNDEFINED_DELTA, UNDEFINED_DELTA, UNDEFINED_DELTA); ClearSemaphore (GraphicsSem); return (i); } break; } } return (1); } return (0); }
// Only call from main() thread!! void TFB_FlushGraphics (void) { int commands_handled; BOOLEAN livelock_deterrence; // This is technically a locking violation on DrawCommandQueue.Size, // but it is likely to not be very destructive. if (DrawCommandQueue.Size == 0) { static int last_fade = 255; static int last_transition = 255; int current_fade = GetFadeAmount (); int current_transition = TransitionAmount; if ((current_fade != 255 && current_fade != last_fade) || (current_transition != 255 && current_transition != last_transition) || (current_fade == 255 && last_fade != 255) || (current_transition == 255 && last_transition != 255)) { TFB_SwapBuffers (TFB_REDRAW_FADING); // if fading, redraw every frame } else { TaskSwitch (); } last_fade = current_fade; last_transition = current_transition; BroadcastCondVar (RenderingCond); return; } if (GfxFlags & TFB_GFXFLAGS_SHOWFPS) computeFPS (); commands_handled = 0; livelock_deterrence = FALSE; if (DrawCommandQueue.FullSize > DCQ_FORCE_BREAK_SIZE) { TFB_BatchReset (); } if (DrawCommandQueue.Size > DCQ_FORCE_SLOWDOWN_SIZE) { Lock_DCQ (-1); livelock_deterrence = TRUE; } TFB_BBox_Reset (); for (;;) { TFB_DrawCommand DC; if (!TFB_DrawCommandQueue_Pop (&DC)) { // the Queue is now empty. break; } ++commands_handled; if (!livelock_deterrence && commands_handled + DrawCommandQueue.Size > DCQ_LIVELOCK_MAX) { // log_add (log_Debug, "Initiating livelock deterrence!"); livelock_deterrence = TRUE; Lock_DCQ (-1); } switch (DC.Type) { case TFB_DRAWCOMMANDTYPE_SETMIPMAP: { TFB_DrawCommand_SetMipmap *cmd = &DC.data.setmipmap; TFB_DrawImage_SetMipmap (cmd->image, cmd->mipmap, cmd->hotx, cmd->hoty); break; } case TFB_DRAWCOMMANDTYPE_IMAGE: { TFB_DrawCommand_Image *cmd = &DC.data.image; TFB_Image *DC_image = cmd->image; const int x = cmd->x; const int y = cmd->y; TFB_DrawCanvas_Image (DC_image, x, y, cmd->scale, cmd->scaleMode, cmd->colormap, cmd->drawMode, TFB_GetScreenCanvas (cmd->destBuffer)); if (cmd->destBuffer == TFB_SCREEN_MAIN) { LockMutex (DC_image->mutex); if (cmd->scale) TFB_BBox_RegisterCanvas (DC_image->ScaledImg, x - DC_image->last_scale_hs.x, y - DC_image->last_scale_hs.y); else TFB_BBox_RegisterCanvas (DC_image->NormalImg, x - DC_image->NormalHs.x, y - DC_image->NormalHs.y); UnlockMutex (DC_image->mutex); } break; } case TFB_DRAWCOMMANDTYPE_FILLEDIMAGE: { TFB_DrawCommand_FilledImage *cmd = &DC.data.filledimage; TFB_Image *DC_image = cmd->image; const int x = cmd->x; const int y = cmd->y; TFB_DrawCanvas_FilledImage (DC_image, x, y, cmd->scale, cmd->scaleMode, cmd->color, cmd->drawMode, TFB_GetScreenCanvas (cmd->destBuffer)); if (cmd->destBuffer == TFB_SCREEN_MAIN) { LockMutex (DC_image->mutex); if (cmd->scale) TFB_BBox_RegisterCanvas (DC_image->ScaledImg, x - DC_image->last_scale_hs.x, y - DC_image->last_scale_hs.y); else TFB_BBox_RegisterCanvas (DC_image->NormalImg, x - DC_image->NormalHs.x, y - DC_image->NormalHs.y); UnlockMutex (DC_image->mutex); } break; } case TFB_DRAWCOMMANDTYPE_FONTCHAR: { TFB_DrawCommand_FontChar *cmd = &DC.data.fontchar; TFB_Char *DC_char = cmd->fontchar; const int x = cmd->x; const int y = cmd->y; TFB_DrawCanvas_FontChar (DC_char, cmd->backing, x, y, cmd->drawMode, TFB_GetScreenCanvas (cmd->destBuffer)); if (cmd->destBuffer == TFB_SCREEN_MAIN) { RECT r; r.corner.x = x - DC_char->HotSpot.x; r.corner.y = y - DC_char->HotSpot.y; r.extent.width = DC_char->extent.width; r.extent.height = DC_char->extent.height; TFB_BBox_RegisterRect (&r); } break; } case TFB_DRAWCOMMANDTYPE_LINE: { TFB_DrawCommand_Line *cmd = &DC.data.line; if (cmd->destBuffer == TFB_SCREEN_MAIN) { TFB_BBox_RegisterPoint (cmd->x1, cmd->y1); TFB_BBox_RegisterPoint (cmd->x2, cmd->y2); } TFB_DrawCanvas_Line (cmd->x1, cmd->y1, cmd->x2, cmd->y2, cmd->color, cmd->drawMode, TFB_GetScreenCanvas (cmd->destBuffer)); break; } case TFB_DRAWCOMMANDTYPE_RECTANGLE: { TFB_DrawCommand_Rect *cmd = &DC.data.rect; if (cmd->destBuffer == TFB_SCREEN_MAIN) TFB_BBox_RegisterRect (&cmd->rect); TFB_DrawCanvas_Rect (&cmd->rect, cmd->color, cmd->drawMode, TFB_GetScreenCanvas (cmd->destBuffer)); break; } case TFB_DRAWCOMMANDTYPE_SCISSORENABLE: { TFB_DrawCommand_Scissor *cmd = &DC.data.scissor; TFB_DrawCanvas_SetClipRect ( TFB_GetScreenCanvas (TFB_SCREEN_MAIN), &cmd->rect); TFB_BBox_SetClipRect (&DC.data.scissor.rect); break; } case TFB_DRAWCOMMANDTYPE_SCISSORDISABLE: TFB_DrawCanvas_SetClipRect ( TFB_GetScreenCanvas (TFB_SCREEN_MAIN), NULL); TFB_BBox_SetClipRect (NULL); break; case TFB_DRAWCOMMANDTYPE_COPYTOIMAGE: { TFB_DrawCommand_CopyToImage *cmd = &DC.data.copytoimage; TFB_Image *DC_image = cmd->image; const POINT dstPt = {0, 0}; if (DC_image == 0) { log_add (log_Debug, "DCQ ERROR: COPYTOIMAGE passed null " "image ptr"); break; } LockMutex (DC_image->mutex); TFB_DrawCanvas_CopyRect ( TFB_GetScreenCanvas (cmd->srcBuffer), &cmd->rect, DC_image->NormalImg, dstPt); UnlockMutex (DC_image->mutex); break; } case TFB_DRAWCOMMANDTYPE_COPY: { TFB_DrawCommand_Copy *cmd = &DC.data.copy; const RECT r = cmd->rect; if (cmd->destBuffer == TFB_SCREEN_MAIN) TFB_BBox_RegisterRect (&cmd->rect); TFB_DrawCanvas_CopyRect ( TFB_GetScreenCanvas (cmd->srcBuffer), &r, TFB_GetScreenCanvas (cmd->destBuffer), r.corner); break; } case TFB_DRAWCOMMANDTYPE_DELETEIMAGE: { TFB_Image *DC_image = DC.data.deleteimage.image; TFB_DrawImage_Delete (DC_image); break; } case TFB_DRAWCOMMANDTYPE_DELETEDATA: { void *data = DC.data.deletedata.data; HFree (data); break; } case TFB_DRAWCOMMANDTYPE_SENDSIGNAL: ClearSemaphore (DC.data.sendsignal.sem); break; case TFB_DRAWCOMMANDTYPE_REINITVIDEO: { TFB_DrawCommand_ReinitVideo *cmd = &DC.data.reinitvideo; int oldDriver = GraphicsDriver; int oldFlags = GfxFlags; int oldWidth = ScreenWidthActual; int oldHeight = ScreenHeightActual; // JMS_GFX: Added resolutionFactor if (TFB_ReInitGraphics (cmd->driver, cmd->flags, cmd->width, cmd->height, resolutionFactor)) { log_add (log_Error, "Could not provide requested mode: " "reverting to last known driver."); // We don't know what exactly failed, so roll it all back if (TFB_ReInitGraphics (oldDriver, oldFlags, oldWidth, oldHeight, resolutionFactor)) { log_add (log_Fatal, "Couldn't reinit at that point either. " "Your video has been somehow tied in knots."); exit (EXIT_FAILURE); } } TFB_SwapBuffers (TFB_REDRAW_YES); break; } case TFB_DRAWCOMMANDTYPE_CALLBACK: { DC.data.callback.callback (DC.data.callback.arg); break; } } } if (livelock_deterrence) Unlock_DCQ (); TFB_SwapBuffers (TFB_REDRAW_NO); RenderedFrames++; BroadcastCondVar (RenderingCond); }
BOOLEAN PauseGame (void) { RECT r; STAMP s; BOOLEAN ClockActive; CONTEXT OldContext; FRAME F; HOT_SPOT OldHot; if (ActivityFrame == 0 || (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_PAUSE)) || (LastActivity & (CHECK_LOAD | CHECK_RESTART))) return (FALSE); GLOBAL (CurrentActivity) |= CHECK_PAUSE; ClockActive = (BOOLEAN)( LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE && GameClockRunning () ); if (ClockActive) SuspendGameClock (); else if (CommData.ConversationPhrases && PlayingTrack ()) PauseTrack (); SetSemaphore (GraphicsSem); OldContext = SetContext (ScreenContext); OldHot = SetFrameHot (Screen, MAKE_HOT_SPOT (0, 0)); GetFrameRect (ActivityFrame, &r); r.corner.x = (SCREEN_WIDTH - r.extent.width) >> 1; r.corner.y = (SCREEN_HEIGHT - r.extent.height) >> 1; s.origin = r.corner; s.frame = ActivityFrame; F = CaptureDrawable (LoadDisplayPixmap (&r, (FRAME)0)); DrawStamp (&s); FlushGraphics (); { BYTE scan; scan = KBDToUNICODE (SK_F1); while (KeyDown (scan)) TaskSwitch (); } FlushInput (); while (KeyHit () != SK_F1) TaskSwitch (); s.frame = F; DrawStamp (&s); DestroyDrawable (ReleaseDrawable (s.frame)); SetFrameHot (Screen, OldHot); SetContext (OldContext); WaitForNoInput (ONE_SECOND / 4); FlushInput (); ClearSemaphore (GraphicsSem); if (ClockActive) ResumeGameClock (); else if (CommData.ConversationPhrases && PlayingTrack ()) ResumeTrack (); TaskSwitch (); GLOBAL (CurrentActivity) &= ~CHECK_PAUSE; return (TRUE); }