GSTexture* GSRendererSW::GetOutput(int i, int& y_offset) { Sync(1); const GSRegDISPFB& DISPFB = m_regs->DISP[i].DISPFB; int w = DISPFB.FBW * 64; int h = GetFrameRect(i).bottom; // TODO: round up bottom if(m_dev->ResizeTexture(&m_texture[i], w, h)) { static int pitch = 1024 * 4; GSVector4i r(0, 0, w, h); const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[DISPFB.PSM]; (m_mem.*psm.rtx)(m_mem.GetOffset(DISPFB.Block(), DISPFB.FBW, DISPFB.PSM), r.ralign<Align_Outside>(psm.bs), m_output, pitch, m_env.TEXA); m_texture[i]->Update(r, m_output, pitch); if(s_dump) { if(s_savef && s_n >= s_saven) { m_texture[i]->Save(m_dump_root + format("%05d_f%lld_fr%d_%05x_%s.bmp", s_n, m_perfmon.GetFrame(), i, (int)DISPFB.Block(), psm_str(DISPFB.PSM))); } } } return m_texture[i]; }
// Draw the full restart menu. Nothing is done with selections. static void DrawRestartMenuGraphic (MENU_STATE *pMS) { RECT r; STAMP s; TEXT t; UNICODE buf[64]; s.frame = pMS->CurFrame; GetFrameRect (s.frame, &r); s.origin.x = (SCREEN_WIDTH - r.extent.width) >> 1; s.origin.y = (SCREEN_HEIGHT - r.extent.height) >> 1; SetContextBackGroundColor (BLACK_COLOR); BatchGraphics (); ClearDrawable (); FlushColorXForms (); DrawStamp (&s); // Put the version number in the bottom right corner. SetContextFont (TinyFont); t.pStr = buf; t.baseline.x = SCREEN_WIDTH - 3; t.baseline.y = SCREEN_HEIGHT - 2; t.align = ALIGN_RIGHT; t.CharCount = (COUNT)~0; sprintf (buf, "v%d.%d.%d%s", UQM_MAJOR_VERSION, UQM_MINOR_VERSION, UQM_PATCH_VERSION, UQM_EXTRA_VERSION); SetContextForeGroundColor (WHITE_COLOR); font_DrawText (&t); UnbatchGraphics (); }
GSTexture* GSRendererHW::GetOutput(int i) { const GSRegDISPFB& DISPFB = m_regs->DISP[i].DISPFB; GIFRegTEX0 TEX0; TEX0.TBP0 = DISPFB.Block(); TEX0.TBW = DISPFB.FBW; TEX0.PSM = DISPFB.PSM; // TRACE(_T("[%d] GetOutput %d %05x (%d)\n"), (int)m_perfmon.GetFrame(), i, (int)TEX0.TBP0, (int)TEX0.PSM); GSTexture* t = NULL; if(GSTextureCache::Target* rt = m_tc->LookupTarget(TEX0, m_width, m_height, GetFrameRect(i).bottom)) { t = rt->m_texture; if(s_dump) { if(s_savef && s_n >= s_saven) { t->Save(root_hw + format("%05d_f%lld_fr%d_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), i, (int)TEX0.TBP0, (int)TEX0.PSM)); } } s_n++; // Alaways increment it } return t; }
GSTexture* GSRendererHW::GetOutput(int i, int& y_offset) { const GSRegDISPFB& DISPFB = m_regs->DISP[i].DISPFB; GIFRegTEX0 TEX0; TEX0.TBP0 = DISPFB.Block(); TEX0.TBW = DISPFB.FBW; TEX0.PSM = DISPFB.PSM; // TRACE(_T("[%d] GetOutput %d %05x (%d)\n"), (int)m_perfmon.GetFrame(), i, (int)TEX0.TBP0, (int)TEX0.PSM); GSTexture* t = NULL; if(GSTextureCache::Target* rt = m_tc->LookupTarget(TEX0, m_width, m_height, GetFrameRect(i).bottom)) { t = rt->m_texture; int delta = TEX0.TBP0 - rt->m_TEX0.TBP0; if (delta > 0) { // Code was corrected to use generic format. But I'm not sure behavior is correct. // Let's keep the warning to easily spot game that trigger this code path. #ifndef DISABLE_WIP_ASSERTION ASSERT(DISPFB.PSM == PSM_PSMCT32 || DISPFB.PSM == PSM_PSMCT24); #endif int pages = delta >> 5u; int y_pages = pages / DISPFB.FBW; y_offset = y_pages * GSLocalMemory::m_psm[DISPFB.PSM].pgs.y; GL_CACHE("Frame y offset %d pixels, unit %d", y_offset, i); }
static void RefreshResponses (ENCOUNTER_STATE *pES) { COORD y; BYTE response, extra_y; // JMS_GFX SIZE leading; STAMP s; SetContext (SpaceContext); GetContextFontLeading (&leading); BatchGraphics (); DrawSISComWindow (); y = SLIDER_Y + SLIDER_HEIGHT + RES_SCALE(1); // JMS_GFX for (response = pES->top_response; response < pES->num_responses; ++response) { extra_y = (response == pES->top_response ? 0 : IF_HD(22)); // JMS_GFX pES->response_list[response].response_text.baseline.x = TEXT_X_OFFS + RES_SCALE(8); // JMS_GFX pES->response_list[response].response_text.baseline.y = y + leading + extra_y; // JMS_GFX pES->response_list[response].response_text.align = ALIGN_LEFT; if (response == pES->cur_response) y = add_text (-1, &pES->response_list[response].response_text); else y = add_text (-2, &pES->response_list[response].response_text); } if (pES->top_response) { s.origin.y = SLIDER_Y + SLIDER_HEIGHT + 1; s.frame = SetAbsFrameIndex (ActivityFrame, 6); } else if (y > SIS_SCREEN_HEIGHT) { s.origin.y = SIS_SCREEN_HEIGHT - 2; s.frame = SetAbsFrameIndex (ActivityFrame, 7); } else s.frame = 0; if (s.frame) { RECT r; GetFrameRect (s.frame, &r); s.origin.x = SIS_SCREEN_WIDTH - r.extent.width - 1; DrawStamp (&s); } UnbatchGraphics (); }
static void pump_up_collision (ELEMENT *ElementPtr0, POINT *pPt0, ELEMENT *ElementPtr1, POINT *pPt1) { RECT r; BYTE old_thrust_wait; HELEMENT hBlastElement; GetFrameRect (ElementPtr0->next.image.frame, &r); old_thrust_wait = ElementPtr0->thrust_wait; ElementPtr0->blast_offset = r.extent.width >> 1; hBlastElement = weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); // This new section kills suspended blaster pulses after sustaining massive burst damage. if (ElementPtr1->mass_points >= ElementPtr0->mass_points) { ElementPtr0->postprocess_func = 0; ElementPtr0->thrust_wait = 0; ElementPtr0->state_flags |= DISAPPEARING; } else ElementPtr0->thrust_wait = old_thrust_wait; if (hBlastElement) { ELEMENT *BlastElementPtr; LockElement (hBlastElement, &BlastElementPtr); BlastElementPtr->life_span = MIN_PUMPITUDE_ANIMS + (ElementPtr0->turn_wait & ~REVERSE_DIR); BlastElementPtr->turn_wait = BlastElementPtr->next_turn = 0; { BlastElementPtr->preprocess_func = animate; } BlastElementPtr->current.image.farray = ElementPtr0->next.image.farray; BlastElementPtr->current.image.frame = SetAbsFrameIndex (BlastElementPtr->current.image.farray[0], MAX_PUMP * NUM_PUMP_ANIMS); UnlockElement (hBlastElement); } }
void GSRendererSW::VSync(int field) { Sync(0); // IncAge might delete a cached texture in use if(0) if(LOG) { fprintf(s_fp, "%llu\n", m_perfmon.GetFrame()); GSVector4i dr = GetDisplayRect(); GSVector4i fr = GetFrameRect(); fprintf(s_fp, "dr %d %d %d %d, fr %d %d %d %d\n", dr.x, dr.y, dr.z, dr.w, fr.x, fr.y, fr.z, fr.w); m_regs->Dump(s_fp); fflush(s_fp); } /* int draw[8], sum = 0; for(size_t i = 0; i < countof(draw); i++) { draw[i] = m_perfmon.CPU(GSPerfMon::WorkerDraw0 + i); sum += draw[i]; } printf("CPU %d Sync %d W %d %d %d %d %d %d %d %d (%d)\n", m_perfmon.CPU(GSPerfMon::Main), m_perfmon.CPU(GSPerfMon::Sync), draw[0], draw[1], draw[2], draw[3], draw[4], draw[5], draw[6], draw[7], sum); // */ GSRenderer::VSync(field); m_tc->IncAge(); // if((m_perfmon.GetFrame() & 255) == 0) m_rl->PrintStats(); }
GSTexture* GSRendererCL::GetOutput(int i) { const GSRegDISPFB& DISPFB = m_regs->DISP[i].DISPFB; int w = DISPFB.FBW * 64; int h = GetFrameRect(i).bottom; // TODO: round up bottom if(m_dev->ResizeTexture(&m_texture[i], w, h)) { static int pitch = 1024 * 4; GSVector4i r(0, 0, w, h); const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[DISPFB.PSM]; GIFRegBITBLTBUF BITBLTBUF; BITBLTBUF.SBP = DISPFB.Block(); BITBLTBUF.SBW = DISPFB.FBW; BITBLTBUF.SPSM = DISPFB.PSM; InvalidateLocalMem(BITBLTBUF, r); (m_mem.*psm.rtx)(m_mem.GetOffset(DISPFB.Block(), DISPFB.FBW, DISPFB.PSM), r.ralign<Align_Outside>(psm.bs), m_output, pitch, m_env.TEXA); m_texture[i]->Update(r, m_output, pitch); if(s_dump) { if(s_save && s_n >= s_saven) { m_texture[i]->Save(format("c:\\temp1\\_%05d_f%lld_fr%d_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), i, (int)DISPFB.Block(), (int)DISPFB.PSM)); } s_n++; } } return m_texture[i]; }
static void DrawRestartMenuGraphic (MENU_STATE *pMS) { RECT r; STAMP s; s.frame = CaptureDrawable (LoadGraphic (RESTART_PMAP_ANIM)); pMS->CurFrame = s.frame; GetFrameRect (s.frame, &r); s.origin.x = (SCREEN_WIDTH - r.extent.width) >> 1; s.origin.y = (SCREEN_HEIGHT - r.extent.height) >> 1; SetContextBackGroundColor (BLACK_COLOR); BatchGraphics (); ClearDrawable (); FlushColorXForms (); LockMutex (GraphicsLock); DrawStamp (&s); UnlockMutex (GraphicsLock); UnbatchGraphics (); }
DirectKey::~DirectKey() { DEC_NDOBJ_RTCLS s_Rect = GetFrameRect(); SAFE_DELETE(m_picNormal); SAFE_DELETE(m_picDown); SAFE_DELETE(m_picCenterNormal); SAFE_DELETE(m_picCenterShrink); if (!m_addShrink) { SAFE_DELETE_NODE(m_btnShrink); } delete m_timer; }
static void pump_up_collision (ELEMENT *ElementPtr0, POINT *pPt0, ELEMENT *ElementPtr1, POINT *pPt1) { RECT r; BYTE old_thrust_wait; HELEMENT hBlastElement; GetFrameRect (ElementPtr0->next.image.frame, &r); old_thrust_wait = ElementPtr0->thrust_wait; ElementPtr0->blast_offset = r.extent.width >> 1; hBlastElement = weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); ElementPtr0->thrust_wait = old_thrust_wait; if (hBlastElement) { ELEMENT *BlastElementPtr; LockElement (hBlastElement, &BlastElementPtr); BlastElementPtr->life_span = MIN_PUMPITUDE_ANIMS + (ElementPtr0->turn_wait & ~REVERSE_DIR); BlastElementPtr->turn_wait = BlastElementPtr->next_turn = 0; { BlastElementPtr->preprocess_func = animate; } BlastElementPtr->current.image.farray = ElementPtr0->next.image.farray; BlastElementPtr->current.image.frame = SetAbsFrameIndex (BlastElementPtr->current.image.farray[0], MAX_PUMP * NUM_PUMP_ANIMS); UnlockElement (hBlastElement); } }
// Draw the value of the fleet in the top right of the PickMeleeFrame. // Pre: caller holds the graphics lock. static void UpdatePickMeleeFleetValue (FRAME frame, COUNT which_player) { CONTEXT OldContext; COUNT value; RECT r; TEXT t; UNICODE buf[40]; value = GetRaceQueueValue (&race_q[which_player]); OldContext = SetContext (OffScreenContext); SetContextFGFrame (frame); // Erase the old value text. GetFrameRect (frame, &r); r.extent.width -= RES_SCALE(4); t.baseline.x = r.extent.width; r.corner.x = r.extent.width - RES_SCALE(6 * 3); // JMS_GFX r.corner.y = RES_SCALE(2); // JMS_GFX r.extent.width = RES_SCALE(6 * 3); // JMS_GFX r.extent.height = RES_SCALE(7 - 2) + RESOLUTION_FACTOR; // JMS_GFX SetContextForeGroundColor (PICK_BG_COLOR); DrawFilledRectangle (&r); // Draw the new value text. sprintf (buf, "%d", value); t.baseline.y = RES_SCALE(7); t.align = ALIGN_RIGHT; t.pStr = buf; t.CharCount = (COUNT)~0; SetContextFont (TinyFont); SetContextForeGroundColor (PICK_VALUE_COLOR); font_DrawText (&t); SetContext (OldContext); }
// Draw the full restart menu. Nothing is done with selections. static void DrawRestartMenuGraphic (MENU_STATE *pMS) { RECT r; STAMP s; TEXT t; char *Credit; UNICODE buf[64]; // Re-load all of the restart menu fonts so the text shows in correct size after changing the resolution. if (optRequiresRestart || !PacksInstalled()) { DestroyFont (TinyFont); DestroyFont (PlyrFont); DestroyFont (StarConFont); } // DC: Load the different menus and fonts depending on the resolution factor switch (resolutionFactor){ case 1: if (optRequiresRestart || !PacksInstalled()) { TinyFont = LoadFont (TINY_FALLBACK_TO2X_FONT); PlyrFont = LoadFont (PLYR_FALLBACK_TO2X_FONT); StarConFont = LoadFont (SCON_FALLBACK_TO2X_FONT); } pMS->CurFrame = CaptureDrawable (LoadGraphic (RESTART_PMAP_ANIM2x)); break; case 2: if (optRequiresRestart || !PacksInstalled()) { TinyFont = LoadFont (TINY_FALLBACK_TO4X_FONT); PlyrFont = LoadFont (PLYR_FALLBACK_TO4X_FONT); StarConFont = LoadFont (SCON_FALLBACK_TO4X_FONT); } pMS->CurFrame = CaptureDrawable (LoadGraphic (RESTART_PMAP_ANIM4x)); break; case 0: default: if (optRequiresRestart || !PacksInstalled()) { TinyFont = LoadFont (TINY_FALLBACK_TO1X_FONT); PlyrFont = LoadFont (PLYR_FALLBACK_TO1X_FONT); StarConFont = LoadFont (SCON_FALLBACK_TO1X_FONT); } pMS->CurFrame = CaptureDrawable (LoadGraphic (RESTART_PMAP_ANIM)); break; } s.frame = pMS->CurFrame; GetFrameRect (s.frame, &r); s.origin.x = (SCREEN_WIDTH - r.extent.width) >> 1; s.origin.y = (SCREEN_HEIGHT - r.extent.height) >> 1; SetContextBackGroundColor (BLACK_COLOR); BatchGraphics (); ClearDrawable (); FlushColorXForms (); DrawStamp (&s); // Put the version number in the bottom right corner. SetContextFont (TinyFont); t.pStr = buf; t.baseline.x = SCREEN_WIDTH - RES_SCALE(2); t.baseline.y = SCREEN_HEIGHT - RES_SCALE(2); t.align = ALIGN_RIGHT; t.CharCount = (COUNT)~0; sprintf (buf, "v%d.%d.%d %s", UQM_MAJOR_VERSION, UQM_MINOR_VERSION, UQM_PATCH_VERSION, UQM_EXTRA_VERSION); SetContextForeGroundColor (WHITE_COLOR); font_DrawText (&t); // Put the main menu music credit in the bottom left corner. memset(&buf[0], 0, sizeof(buf)); t.baseline.x = RES_SCALE(2); t.baseline.y = SCREEN_HEIGHT - RES_SCALE(2); t.align = ALIGN_LEFT; Credit = (Rando == 0 ? "Saibuster" : (Rando == 1 ? "Rush AX" : "Mark Vera")); sprintf (buf, "Main Menu Music by %s", Credit); font_DrawText (&t); UnbatchGraphics (); }
void WebDropBox::DrawThisOnly (DISPLAY_INT x, DISPLAY_INT y, WebGraphics *gc) { WEBC_BOOL focused = (mFlags & DISPLAY_FLAG_FOCUS) || (mState == DROPBOX_STATE_DROPPED); mListbox.CalculateTextMetrics(gc); WebRect oldClip; gc->GetClip(&oldClip); WebRect clip; clip.top = y; clip.left = x; clip.bottom = y + Height() - 1; clip.right = x + Width() - 1; clip.And(&oldClip); gc->SetClip(&clip); WebRect rect; rect.top = y; rect.left = x; rect.bottom = y + Height() - 1; rect.right = x + Width() - 1; // gc->StartBuffer(); WebColor hilite, lolite, blue, white, black; HTMLColor col = HTML_RGBAToColor(0,0,0,0); black = hilite = gc->RGBToColor(col); col = HTML_RGBAToColor(0xff,0xff,0xff,0); white = lolite = gc->RGBToColor(col); col = HTML_RGBAToColor(0,0,0xff,0); blue = gc->RGBToColor(col); if (focused) { gc->Rectangle(&rect, black, black, WEBC_FALSE); } GetFrameRect(&rect); rect.Shift(x,y); DrawFrame(&rect, gc); GetContentRect(&rect); rect.Shift(x,y); if (focused) { gc->Rectangle(&rect, GetSelectColor(gc), GetSelectColor(gc), WEBC_TRUE); } else { gc->Rectangle(&rect, GetBgColor(gc), GetBgColor(gc), WEBC_TRUE); } if (mpText && mFont.GetFont()) { DISPLAY_INT offset = (rect.Height() - gc->TextHeight(mpText, mFont.GetFont())) / 2; clip.Set(&rect); clip.And(&oldClip); gc->SetClip(&clip); gc->Text(rect.left + DROPBOX_PADDING, rect.top + DROPBOX_PADDING + offset, mpText, (focused) ? GetBgColor(gc) : GetTextColor(gc), 0, WEBC_FALSE, mFont.GetFont()); } // gc->EndBuffer(); gc->SetClip(&oldClip); }
bool GSRenderer::Merge(int field) { bool en[2]; GSVector4i fr[2]; GSVector4i dr[2]; GSVector2i display_baseline = { INT_MAX, INT_MAX }; GSVector2i frame_baseline = { INT_MAX, INT_MAX }; for(int i = 0; i < 2; i++) { en[i] = IsEnabled(i); if(en[i]) { fr[i] = GetFrameRect(i); dr[i] = GetDisplayRect(i); display_baseline.x = min(dr[i].left, display_baseline.x); display_baseline.y = min(dr[i].top, display_baseline.y); frame_baseline.x = min(fr[i].left, frame_baseline.x); frame_baseline.y = min(fr[i].top, frame_baseline.y); //printf("[%d]: %d %d %d %d, %d %d %d %d\n", i, fr[i].x,fr[i].y,fr[i].z,fr[i].w , dr[i].x,dr[i].y,dr[i].z,dr[i].w); } } if(!en[0] && !en[1]) { return false; } GL_PUSH("Renderer Merge %d (0: enabled %d 0x%x, 1: enabled %d 0x%x)", s_n, en[0], m_regs->DISP[0].DISPFB.Block(), en[1], m_regs->DISP[1].DISPFB.Block()); // try to avoid fullscreen blur, could be nice on tv but on a monitor it's like double vision, hurts my eyes (persona 4, guitar hero) // // NOTE: probably the technique explained in graphtip.pdf (Antialiasing by Supersampling / 4. Reading Odd/Even Scan Lines Separately with the PCRTC then Blending) bool samesrc = en[0] && en[1] && m_regs->DISP[0].DISPFB.FBP == m_regs->DISP[1].DISPFB.FBP && m_regs->DISP[0].DISPFB.FBW == m_regs->DISP[1].DISPFB.FBW && m_regs->DISP[0].DISPFB.PSM == m_regs->DISP[1].DISPFB.PSM; if(samesrc /*&& m_regs->PMODE.SLBG == 0 && m_regs->PMODE.MMOD == 1 && m_regs->PMODE.ALP == 0x80*/) { // persona 4: // // fr[0] = 0 0 640 448 // fr[1] = 0 1 640 448 // dr[0] = 159 50 779 498 // dr[1] = 159 50 779 497 // // second image shifted up by 1 pixel and blended over itself // // god of war: // // fr[0] = 0 1 512 448 // fr[1] = 0 0 512 448 // dr[0] = 127 50 639 497 // dr[1] = 127 50 639 498 // // same just the first image shifted // // These kinds of cases are now fixed by the more generic frame_diff code below, as the code here was too specific and has become obsolete. // NOTE: Persona 4 and God Of War are not rare exceptions, many games have the same(or very similar) offsets. int topDiff = fr[0].top - fr[1].top; if (dr[0].eq(dr[1]) && (fr[0].eq(fr[1] + GSVector4i(0, topDiff, 0, topDiff)) || fr[1].eq(fr[0] + GSVector4i(0, topDiff, 0, topDiff)))) { // dq5: // // fr[0] = 0 1 512 445 // fr[1] = 0 0 512 444 // dr[0] = 127 50 639 494 // dr[1] = 127 50 639 494 int top = min(fr[0].top, fr[1].top); int bottom = min(fr[0].bottom, fr[1].bottom); fr[0].top = fr[1].top = top; fr[0].bottom = fr[1].bottom = bottom; } } GSVector2i fs(0, 0); GSVector2i ds(0, 0); GSTexture* tex[3] = {NULL, NULL, NULL}; int y_offset[3] = {0, 0, 0}; s_n++; bool feedback_merge = m_regs->EXTWRITE.WRITE == 1; if(samesrc && fr[0].bottom == fr[1].bottom && !feedback_merge) { tex[0] = GetOutput(0, y_offset[0]); tex[1] = tex[0]; // saves one texture fetch y_offset[1] = y_offset[0]; } else { if(en[0]) tex[0] = GetOutput(0, y_offset[0]); if(en[1]) tex[1] = GetOutput(1, y_offset[1]); if(feedback_merge) tex[2] = GetFeedbackOutput(); } GSVector4 src[2]; GSVector4 src_hw[2]; GSVector4 dst[2]; for(int i = 0; i < 2; i++) { if(!en[i] || !tex[i]) continue; GSVector4i r = fr[i]; GSVector4 scale = GSVector4(tex[i]->GetScale()).xyxy(); src[i] = GSVector4(r) * scale / GSVector4(tex[i]->GetSize()).xyxy(); src_hw[i] = (GSVector4(r) + GSVector4 (0, y_offset[i], 0, y_offset[i])) * scale / GSVector4(tex[i]->GetSize()).xyxy(); GSVector2 off(0); GSVector2i display_diff(dr[i].left - display_baseline.x, dr[i].top - display_baseline.y); GSVector2i frame_diff(fr[i].left - frame_baseline.x, fr[i].top - frame_baseline.y); // Time Crisis 2/3 uses two side by side images when in split screen mode. // Though ignore cases where baseline and display rectangle offsets only differ by 1 pixel, causes blurring and wrong resolution output on FFXII if(display_diff.x > 2) { off.x = tex[i]->GetScale().x * display_diff.x; } // If the DX offset is too small then consider the status of frame memory offsets, prevents blurring on Tenchu: Fatal Shadows, Worms 3D else if(display_diff.x != frame_diff.x) { off.x = tex[i]->GetScale().x * frame_diff.x; } if(display_diff.y >= 4) // Shouldn't this be >= 2? { off.y = tex[i]->GetScale().y * display_diff.y; if(m_regs->SMODE2.INT && m_regs->SMODE2.FFMD) { off.y /= 2; } } else if(display_diff.y != frame_diff.y) { off.y = tex[i]->GetScale().y * frame_diff.y; } dst[i] = GSVector4(off).xyxy() + scale * GSVector4(r.rsize()); fs.x = max(fs.x, (int)(dst[i].z + 0.5f)); fs.y = max(fs.y, (int)(dst[i].w + 0.5f)); } ds = fs; if(m_regs->SMODE2.INT && m_regs->SMODE2.FFMD) { ds.y *= 2; } m_real_size = ds; bool slbg = m_regs->PMODE.SLBG; if(tex[0] || tex[1]) { if(tex[0] == tex[1] && !slbg && (src[0] == src[1] & dst[0] == dst[1]).alltrue()) { // the two outputs are identical, skip drawing one of them (the one that is alpha blended) tex[0] = NULL; } GSVector4 c = GSVector4((int)m_regs->BGCOLOR.R, (int)m_regs->BGCOLOR.G, (int)m_regs->BGCOLOR.B, (int)m_regs->PMODE.ALP) / 255; m_dev->Merge(tex, src_hw, dst, fs, m_regs->PMODE, m_regs->EXTBUF, c); if(m_regs->SMODE2.INT && m_interlace > 0) { if(m_interlace == 7 && m_regs->SMODE2.FFMD) // Auto interlace enabled / Odd frame interlace setting { int field2 = 0; int mode = 2; m_dev->Interlace(ds, field ^ field2, mode, tex[1] ? tex[1]->GetScale().y : tex[0]->GetScale().y); } else { int field2 = 1 - ((m_interlace - 1) & 1); int mode = (m_interlace - 1) >> 1; m_dev->Interlace(ds, field ^ field2, mode, tex[1] ? tex[1]->GetScale().y : tex[0]->GetScale().y); } } if(m_shadeboost) { m_dev->ShadeBoost(); } if(m_shaderfx) { m_dev->ExternalFX(); } if(m_fxaa) { m_dev->FXAA(); } } return true; }
// Put the ship icons in the PickMeleeFrame, and create a queue // for each player. // XXX TODO: split off creating the queue into a separate function. void FillPickMeleeFrame (MeleeSetup *setup) { COUNT i; CONTEXT OldContext; OldContext = SetContext (OffScreenContext); for (i = 0; i < NUM_SIDES; ++i) { COUNT side; COUNT sideI; RECT r; TEXT t; STAMP s; UNICODE buf[30]; FleetShipIndex index; sideI = GetPlayerOrder (i); side = !sideI; s.frame = SetAbsFrameIndex (PickMeleeFrame, side); SetContextFGFrame (s.frame); GetFrameRect (s.frame, &r); t.baseline.x = r.extent.width >> 1; t.baseline.y = r.extent.height - NAME_AREA_HEIGHT + RES_SCALE(4); r.corner.x += RES_SCALE(2); r.corner.y += RES_SCALE(2); r.extent.width -= RES_SCALE((2 * 2) + (RES_DESCALE(ICON_WIDTH) + 2) + 1); // JMS_GFX r.extent.height -= RES_SCALE(2 * 2) + NAME_AREA_HEIGHT; // JMS_GFX SetContextForeGroundColor (PICK_BG_COLOR); DrawFilledRectangle (&r); r.corner.x += RES_SCALE(2); // JMS_GFX r.extent.width += RES_SCALE((RES_DESCALE(ICON_WIDTH) + 2) - (2 * 2)); // JMS_GFX r.corner.y += r.extent.height; r.extent.height = NAME_AREA_HEIGHT; DrawFilledRectangle (&r); // Team name at the bottom of the frame: t.align = ALIGN_CENTER; t.pStr = MeleeSetup_getTeamName (setup, sideI); t.CharCount = (COUNT) ~0; SetContextFont (TinyFont); SetContextForeGroundColor (PICKSHIP_TEAM_NAME_TEXT_COLOR); font_DrawText (&t); // Total team value of the starting team: sprintf (buf, "%u", MeleeSetup_getFleetValue (setup, sideI)); t.baseline.x = RES_SCALE(4); t.baseline.y = RES_SCALE(7); t.align = ALIGN_LEFT; t.pStr = buf; t.CharCount = (COUNT)~0; SetContextForeGroundColor (PICKSHIP_TEAM_START_VALUE_COLOR); font_DrawText (&t); assert (CountLinks (&race_q[side]) == 0); for (index = 0; index < MELEE_FLEET_SIZE; index++) { MeleeShip StarShip; StarShip = MeleeSetup_getShip (setup, sideI, index); if (StarShip == MELEE_NONE) continue; { BYTE row, col; BYTE ship_cost; HMASTERSHIP hMasterShip; HSTARSHIP hBuiltShip; MASTER_SHIP_INFO *MasterPtr; STARSHIP *BuiltShipPtr; BYTE captains_name_index; hMasterShip = GetStarShipFromIndex (&master_q, StarShip); MasterPtr = LockMasterShip (&master_q, hMasterShip); captains_name_index = NameCaptain (&race_q[side], MasterPtr->SpeciesID); hBuiltShip = Build (&race_q[side], MasterPtr->SpeciesID); // Draw the icon. row = PickMelee_GetShipRow (index); col = PickMelee_GetShipColumn (index); s.origin.x = RES_SCALE(4) + ((ICON_WIDTH + RES_SCALE(2)) * col); // JMS_GFX s.origin.y = RES_SCALE(10) + ((ICON_HEIGHT + RES_SCALE(2)) * row); s.frame = MasterPtr->ShipInfo.icons; DrawStamp (&s); ship_cost = MasterPtr->ShipInfo.ship_cost; UnlockMasterShip (&master_q, hMasterShip); BuiltShipPtr = LockStarShip (&race_q[side], hBuiltShip); BuiltShipPtr->index = index; BuiltShipPtr->ship_cost = ship_cost; BuiltShipPtr->playerNr = side; BuiltShipPtr->captains_name_index = captains_name_index; // The next ones are not used in Melee BuiltShipPtr->crew_level = 0; BuiltShipPtr->max_crew = 0; BuiltShipPtr->race_strings = 0; BuiltShipPtr->icons = 0; BuiltShipPtr->RaceDescPtr = 0; UnlockStarShip (&race_q[side], hBuiltShip); } } } SetContext (OldContext); }
// Draw the full restart menu. Nothing is done with selections. static void DrawRestartMenuGraphic (MENU_STATE *pMS) { RECT r; STAMP s; TEXT t; UNICODE buf[64]; COUNT svn_revision = 0; // JMS //DC: Load the different menus depending on the resolution factor if (resolutionFactor < 1) s.frame = CaptureDrawable (LoadGraphic (RESTART_PMAP_ANIM)); if (resolutionFactor == 1) s.frame = CaptureDrawable (LoadGraphic (RESTART_PMAP_ANIM2x)); if (resolutionFactor > 1) s.frame = CaptureDrawable (LoadGraphic (RESTART_PMAP_ANIM4x)); // Re-load the info box font so the text shows in correct size after changing the resolution. if (resFactorWasChanged) { DestroyFont (StarConFont); if (resolutionFactor < 1) StarConFont = LoadFont (FALLBACK_TO1X_FONT); if (resolutionFactor == 1) StarConFont = LoadFont (FALLBACK_TO2X_FONT); if (resolutionFactor > 1) StarConFont = LoadFont (FALLBACK_TO4X_FONT); } pMS->CurFrame = s.frame; GetFrameRect (s.frame, &r); s.origin.x = (SCREEN_WIDTH - r.extent.width) >> 1; s.origin.y = (SCREEN_HEIGHT - r.extent.height) >> 1; SetContextBackGroundColor (BLACK_COLOR); BatchGraphics (); ClearDrawable (); FlushColorXForms (); LockMutex (GraphicsLock); DrawStamp (&s); // JMS: Hack for printing out the correct SVN revision number. { UNICODE svn_buf[64] = {0}; char *colonPtr; strcpy(svn_buf, UQMHD_SVN_REVISION); colonPtr = strchr(svn_buf, ':'); // The revision number is in format rXXX if (colonPtr == NULL) { // Let's just take the only number and be happy. svn_revision = atoi(svn_buf); } // the revision number is in format rXXX:ZZZ else { // Now we need to extract only the ZZZ number. UNICODE svn_buf2[10]; strcpy(svn_buf2, colonPtr+1); svn_revision = atoi(svn_buf2); } // Think about this for a while ;) ++svn_revision; } // Put the version number in the bottom right corner. SetContextFont (TinyFont); t.pStr = buf; t.baseline.x = SCREEN_WIDTH - 3; t.baseline.y = SCREEN_HEIGHT - 2; t.align = ALIGN_RIGHT; t.CharCount = (COUNT)~0; sprintf (buf, "v%d.%d.%d%s - SVN r%d", UQM_MAJOR_VERSION, UQM_MINOR_VERSION, UQM_PATCH_VERSION, UQM_EXTRA_VERSION, svn_revision); SetContextForeGroundColor (WHITE_COLOR); font_DrawText (&t); UnlockMutex (GraphicsLock); UnbatchGraphics (); }
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); }
bool GSRenderer::Merge(int field) { bool en[2]; GSVector4i fr[2]; GSVector4i dr[2]; int baseline = INT_MAX; for(int i = 0; i < 2; i++) { en[i] = IsEnabled(i); if(en[i]) { fr[i] = GetFrameRect(i); dr[i] = GetDisplayRect(i); baseline = min(dr[i].top, baseline); //printf("[%d]: %d %d %d %d, %d %d %d %d\n", i, fr[i].x,fr[i].y,fr[i].z,fr[i].w , dr[i].x,dr[i].y,dr[i].z,dr[i].w); } } if(!en[0] && !en[1]) { return false; } // try to avoid fullscreen blur, could be nice on tv but on a monitor it's like double vision, hurts my eyes (persona 4, guitar hero) // // NOTE: probably the technique explained in graphtip.pdf (Antialiasing by Supersampling / 4. Reading Odd/Even Scan Lines Separately with the PCRTC then Blending) bool samesrc = en[0] && en[1] && m_regs->DISP[0].DISPFB.FBP == m_regs->DISP[1].DISPFB.FBP && m_regs->DISP[0].DISPFB.FBW == m_regs->DISP[1].DISPFB.FBW && m_regs->DISP[0].DISPFB.PSM == m_regs->DISP[1].DISPFB.PSM; // bool blurdetected = false; if(samesrc /*&& m_regs->PMODE.SLBG == 0 && m_regs->PMODE.MMOD == 1 && m_regs->PMODE.ALP == 0x80*/) { if(fr[0].eq(fr[1] + GSVector4i(0, -1, 0, 0)) && dr[0].eq(dr[1] + GSVector4i(0, 0, 0, 1)) || fr[1].eq(fr[0] + GSVector4i(0, -1, 0, 0)) && dr[1].eq(dr[0] + GSVector4i(0, 0, 0, 1))) { // persona 4: // // fr[0] = 0 0 640 448 // fr[1] = 0 1 640 448 // dr[0] = 159 50 779 498 // dr[1] = 159 50 779 497 // // second image shifted up by 1 pixel and blended over itself // // god of war: // // fr[0] = 0 1 512 448 // fr[1] = 0 0 512 448 // dr[0] = 127 50 639 497 // dr[1] = 127 50 639 498 // // same just the first image shifted int top = min(fr[0].top, fr[1].top); int bottom = max(dr[0].bottom, dr[1].bottom); fr[0].top = top; fr[1].top = top; dr[0].bottom = bottom; dr[1].bottom = bottom; // blurdetected = true; } else if(dr[0].eq(dr[1]) && (fr[0].eq(fr[1] + GSVector4i(0, 1, 0, 1)) || fr[1].eq(fr[0] + GSVector4i(0, 1, 0, 1)))) { // dq5: // // fr[0] = 0 1 512 445 // fr[1] = 0 0 512 444 // dr[0] = 127 50 639 494 // dr[1] = 127 50 639 494 int top = min(fr[0].top, fr[1].top); int bottom = min(fr[0].bottom, fr[1].bottom); fr[0].top = fr[1].top = top; fr[0].bottom = fr[1].bottom = bottom; // blurdetected = true; } //printf("samesrc = %d blurdetected = %d\n",samesrc,blurdetected); } GSVector2i fs(0, 0); GSVector2i ds(0, 0); GSTexture* tex[2] = {NULL, NULL}; if(samesrc && fr[0].bottom == fr[1].bottom) { tex[0] = GetOutput(0); tex[1] = tex[0]; // saves one texture fetch } else { if(en[0]) tex[0] = GetOutput(0); if(en[1]) tex[1] = GetOutput(1); } GSVector4 src[2]; GSVector4 dst[2]; for(int i = 0; i < 2; i++) { if(!en[i] || !tex[i]) continue; GSVector4i r = fr[i]; // overscan hack if(dr[i].height() > 512) // hmm { int y = GetDeviceSize(i).y; if(m_regs->SMODE2.INT && m_regs->SMODE2.FFMD) y /= 2; r.bottom = r.top + y; } GSVector4 scale = GSVector4(tex[i]->GetScale()).xyxy(); src[i] = GSVector4(r) * scale / GSVector4(tex[i]->GetSize()).xyxy(); GSVector2 o(0, 0); if(dr[i].top - baseline >= 4) // 2? { o.y = tex[i]->GetScale().y * (dr[i].top - baseline); if(m_regs->SMODE2.INT && m_regs->SMODE2.FFMD) { o.y /= 2; } } dst[i] = GSVector4(o).xyxy() + scale * GSVector4(r.rsize()); fs.x = max(fs.x, (int)(dst[i].z + 0.5f)); fs.y = max(fs.y, (int)(dst[i].w + 0.5f)); } ds = fs; if(m_regs->SMODE2.INT && m_regs->SMODE2.FFMD) { ds.y *= 2; } bool slbg = m_regs->PMODE.SLBG; bool mmod = m_regs->PMODE.MMOD; if(tex[0] || tex[1]) { if(tex[0] == tex[1] && !slbg && (src[0] == src[1] & dst[0] == dst[1]).alltrue()) { // the two outputs are identical, skip drawing one of them (the one that is alpha blended) tex[0] = NULL; } GSVector4 c = GSVector4((int)m_regs->BGCOLOR.R, (int)m_regs->BGCOLOR.G, (int)m_regs->BGCOLOR.B, (int)m_regs->PMODE.ALP) / 255; m_dev->Merge(tex, src, dst, fs, slbg, mmod, c); if(m_regs->SMODE2.INT && m_interlace > 0) { if (m_interlace == 7 && m_regs->SMODE2.FFMD == 1) // Auto interlace enabled / Odd frame interlace setting { int field2 = 0; int mode = 2; m_dev->Interlace(ds, field ^ field2, mode, tex[1] ? tex[1]->GetScale().y : tex[0]->GetScale().y); } else { int field2 = 1 - ((m_interlace - 1) & 1); int mode = (m_interlace - 1) >> 1; m_dev->Interlace(ds, field ^ field2, mode, tex[1] ? tex[1]->GetScale().y : tex[0]->GetScale().y); } } if(m_shadeboost) { m_dev->ShadeBoost(); } if (m_shaderfx) { m_dev->ExternalFX(); } if(m_fxaa) { m_dev->FXAA(); } } return true; }
BOOLEAN DoLoadTeam (MELEE_STATE *pMS) { DWORD TimeIn = GetTimeCounter (); /* Cancel any presses of the Pause key. */ GamePaused = FALSE; if (GLOBAL (CurrentActivity) & CHECK_ABORT) return FALSE; SetMenuSounds (MENU_SOUND_UP | MENU_SOUND_DOWN | MENU_SOUND_PAGEUP | MENU_SOUND_PAGEDOWN, MENU_SOUND_SELECT); if (!pMS->Initialized) { LockMutex (GraphicsLock); DrawFileStrings (pMS); SelectFileString (pMS, true); pMS->Initialized = TRUE; pMS->InputFunc = DoLoadTeam; UnlockMutex (GraphicsLock); return TRUE; } if (PulsedInputState.menu[KEY_MENU_SELECT] || PulsedInputState.menu[KEY_MENU_CANCEL]) { if (PulsedInputState.menu[KEY_MENU_SELECT]) { // Copy the selected fleet to the player. Melee_LocalChange_team (pMS, pMS->side, pMS->load.view[pMS->load.cur - pMS->load.top]); } pMS->InputFunc = DoMelee; pMS->LastInputTime = GetTimeCounter (); { RECT r; GetFrameRect (SetAbsFrameIndex (MeleeFrame, 28), &r); LockMutex (GraphicsLock); RepairMeleeFrame (&r); UnlockMutex (GraphicsLock); } return TRUE; } { COUNT newTop = pMS->load.top; COUNT newIndex = pMS->load.cur; if (PulsedInputState.menu[KEY_MENU_UP]) { if (newIndex > 0) { newIndex--; if (newIndex < newTop) newTop = (newTop < LOAD_TEAM_VIEW_SIZE) ? 0 : newTop - LOAD_TEAM_VIEW_SIZE; } } else if (PulsedInputState.menu[KEY_MENU_DOWN]) { COUNT numEntries = pMS->load.numIndices + pMS->load.preBuiltCount; if (newIndex + 1 < numEntries) { newIndex++; if (newIndex >= pMS->load.bot) newTop = pMS->load.bot; } } else if (PulsedInputState.menu[KEY_MENU_PAGE_UP]) { newIndex = (newIndex < LOAD_TEAM_VIEW_SIZE) ? 0 : newIndex - LOAD_TEAM_VIEW_SIZE; newTop = (newTop < LOAD_TEAM_VIEW_SIZE) ? 0 : newTop - LOAD_TEAM_VIEW_SIZE; } else if (PulsedInputState.menu[KEY_MENU_PAGE_DOWN]) { COUNT numEntries = pMS->load.numIndices + pMS->load.preBuiltCount; if (newIndex + LOAD_TEAM_VIEW_SIZE < numEntries) { newIndex += LOAD_TEAM_VIEW_SIZE; newTop += LOAD_TEAM_VIEW_SIZE; } else { newIndex = numEntries - 1; if (newTop + LOAD_TEAM_VIEW_SIZE < numEntries && numEntries > LOAD_TEAM_VIEW_SIZE) newTop = numEntries - LOAD_TEAM_VIEW_SIZE; } } if (newIndex != pMS->load.cur) { // The cursor has been moved. LockMutex (GraphicsLock); if (newTop == pMS->load.top) { // The view itself hasn't changed. SelectFileString (pMS, false); } else { // The view is changed. pMS->load.top = newTop; DrawFileStrings (pMS); } pMS->load.cur = newIndex; UnlockMutex (GraphicsLock); } } flashSelectedTeam (pMS); SleepThreadUntil (TimeIn + ONE_SECOND / 30); return TRUE; }
void WebEditBox::DrawThisOnly (DISPLAY_INT x, DISPLAY_INT y, WebGraphics *gc) { WebChar c; long line; WebRect box; GetFrameRect(&box); box.Shift(x,y); // gc->StartBuffer(); // begin buffering graphics commands gc->Rectangle(&box, GetBgColor(gc), GetBgColor(gc), 1); // draw background DrawFrame(&box, gc); // save the current graphics context clip rectangle and set clipping to the // text display region of the widget GetTextRect(&box); box.Shift(x,y); WebRect clipSave; gc->GetClip(&clipSave); if (clipSave.Overlaps(&box)) { WebRect clip(box); clip.And(&clipSave); gc->SetClip(&clip); miXOffset = (mpHScroll)? mpHScroll->GetPosition() : 0; miYOffset = (mpVScroll)? mpVScroll->GetPosition() : 0; // render our text WebFont font = mFont.GetFont(); if (mpText && font) { // this loop draws up to the last line for (line=0; line<(miNumLines-1); line++) { c = mpText[GetLineOffset(line+1)]; mpText[GetLineOffset(line+1)] = 0; DrawText(gc, box.left - miXOffset, box.top - miYOffset + (line * WEB_FONT_HEIGHT(font)), mpText + GetLineOffset(line), GetTextColor(gc), 0, 0, font); mpText[GetLineOffset(line+1)] = c; } // now draw the last line of text. DrawText(gc, box.left - miXOffset, box.top - miYOffset + (line*WEB_FONT_HEIGHT(font)), mpText + GetLineOffset(line), GetTextColor(gc), 0, 0, font); // if we have the focus, draw the cursor if ((mFlags & DISPLAY_FLAG_FOCUS) && !(mFlags & DISPLAY_FLAG_DISABLED)) { // now render the selected portion in reverse video (if we have one) if (mEditFlags & EDIT_FLAG_HAS_SELECTION) { long begin = EBSMIN(miCursorPos, miSelectBegin); long end = EBSMAX(miCursorPos, miSelectBegin); long beginLine = FindLine(begin), endLine = FindLine(end); DISPLAY_INT textLeft; long currentBegin, currentEnd; for (line=beginLine; line<=endLine; line++) { currentBegin = EBSMAX(begin, GetLineOffset(line)); if (line == endLine) { currentEnd = end; } else { currentEnd = EBSMIN(end, GetLineOffset(line+1)); } textLeft = gc->TextWidthLen(mpText + GetLineOffset(line), font, EBSMAX(0, begin - GetLineOffset(line))); c = mpText[currentEnd]; mpText[currentEnd] = 0; DrawText(gc, box.left - miXOffset + textLeft, box.top - miYOffset + (line*WEB_FONT_HEIGHT(font)), mpText + currentBegin, GetBgColor(gc), GetSelectColor(gc), 1, font); mpText[currentEnd] = c; } } DISPLAY_INT cursorX = box.left - miXOffset + gc->TextWidthLen(mpText + GetLineOffset(miCurrentLine), font, miCursorPos - GetLineOffset(miCurrentLine)) ; box.Set(cursorX, box.top - miYOffset + WEB_FONT_HEIGHT(font)*miCurrentLine, cursorX, box.top - miYOffset + WEB_FONT_HEIGHT(font)*(miCurrentLine+1)); gc->Rectangle(&box, GetSelectColor(gc), GetSelectColor(gc), 1); } } gc->SetClip(&clipSave); // restore the clip rectangle } // if clip overlaps /* if (mpVScroll && mpHScroll) { GetCornerRect(&box); box.Shift(x,y); gc->Rectangle(&box, LIGHTGRAY, LIGHTGRAY, 1); }*/ // gc->EndBuffer(); // send all buffered commands to the display }
void spawn_ion_trail (ELEMENT *ElementPtr) { STARSHIP *StarShipPtr; SHIP_INFO *ShipInfoPtr; HELEMENT hIonElement; assert (ElementPtr->state_flags & PLAYER_SHIP); // JMS: Get the pointers to element's owner ship. // They are needed to see if the ship's thrust is damaged GetElementStarShip (ElementPtr, &StarShipPtr); ShipInfoPtr = &StarShipPtr->RaceDescPtr->ship_info; hIonElement = AllocElement (); if (hIonElement) { #define ION_LIFE 1 COUNT angle; RECT r; ELEMENT *IonElementPtr; STARSHIP *StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing) + HALF_CIRCLE; GetFrameRect (StarShipPtr->RaceDescPtr->ship_data.ship[0], &r); r.extent.height = DISPLAY_TO_WORLD (r.extent.height + r.corner.y); InsertElement (hIonElement, GetHeadElement ()); LockElement (hIonElement, &IonElementPtr); IonElementPtr->playerNr = NEUTRAL_PLAYER_NUM; IonElementPtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID; IonElementPtr->thrust_wait = ION_LIFE; IonElementPtr->life_span = IonElementPtr->thrust_wait; // When the element "dies", in the death_func // 'cycle_ion_trail', it is given new life a number of // times, by setting life_span to thrust_wait. SetPrimType (&DisplayArray[IonElementPtr->PrimIndex], POINT_PRIM); // JMS: Damaged thruster emits differently colored particles if (ShipInfoPtr->damage_flags & DAMAGE_THRUST) { SetPrimColor (&DisplayArray[IonElementPtr->PrimIndex], START_ION_COLOR_DAMAGED); } else { SetPrimColor (&DisplayArray[IonElementPtr->PrimIndex], START_ION_COLOR); } IonElementPtr->colorCycleIndex = 0; IonElementPtr->current.image.frame = DecFrameIndex (stars_in_space); IonElementPtr->current.image.farray = &stars_in_space; IonElementPtr->current.location = ElementPtr->current.location; IonElementPtr->current.location.x += (COORD)COSINE (angle, r.extent.height); IonElementPtr->current.location.y += (COORD)SINE (angle, r.extent.height); IonElementPtr->death_func = cycle_ion_trail; SetElementStarShip (IonElementPtr, StarShipPtr); { /* normally done during preprocess, but because * object is being inserted at head rather than * appended after tail it may never get preprocessed. */ IonElementPtr->next = IonElementPtr->current; --IonElementPtr->life_span; IonElementPtr->state_flags |= PRE_PROCESS; } UnlockElement (hIonElement); } }
void GSRendererSW::VSync(int field) { Sync(0); // IncAge might delete a cached texture in use if(0) if(LOG) { fprintf(s_fp, "%lld\n", m_perfmon.GetFrame()); GSVector4i dr = GetDisplayRect(); GSVector4i fr = GetFrameRect(); GSVector2i ds = GetDeviceSize(); fprintf(s_fp, "dr %d %d %d %d, fr %d %d %d %d, ds %d %d\n", dr.x, dr.y, dr.z, dr.w, fr.x, fr.y, fr.z, fr.w, ds.x, ds.y); for(int i = 0; i < 2; i++) { if(i == 0 && !m_regs->PMODE.EN1) continue; if(i == 1 && !m_regs->PMODE.EN2) continue; fprintf(s_fp, "DISPFB[%d] BP=%05x BW=%d PSM=%d DBX=%d DBY=%d\n", i, m_regs->DISP[i].DISPFB.Block(), m_regs->DISP[i].DISPFB.FBW, m_regs->DISP[i].DISPFB.PSM, m_regs->DISP[i].DISPFB.DBX, m_regs->DISP[i].DISPFB.DBY ); fprintf(s_fp, "DISPLAY[%d] DX=%d DY=%d DW=%d DH=%d MAGH=%d MAGV=%d\n", i, m_regs->DISP[i].DISPLAY.DX, m_regs->DISP[i].DISPLAY.DY, m_regs->DISP[i].DISPLAY.DW, m_regs->DISP[i].DISPLAY.DH, m_regs->DISP[i].DISPLAY.MAGH, m_regs->DISP[i].DISPLAY.MAGV ); } fprintf(s_fp, "PMODE EN1=%d EN2=%d CRTMD=%d MMOD=%d AMOD=%d SLBG=%d ALP=%d\n", m_regs->PMODE.EN1, m_regs->PMODE.EN2, m_regs->PMODE.CRTMD, m_regs->PMODE.MMOD, m_regs->PMODE.AMOD, m_regs->PMODE.SLBG, m_regs->PMODE.ALP ); fprintf(s_fp, "SMODE1 CLKSEL=%d CMOD=%d EX=%d GCONT=%d LC=%d NVCK=%d PCK2=%d PEHS=%d PEVS=%d PHS=%d PRST=%d PVS=%d RC=%d SINT=%d SLCK=%d SLCK2=%d SPML=%d T1248=%d VCKSEL=%d VHP=%d XPCK=%d\n", m_regs->SMODE1.CLKSEL, m_regs->SMODE1.CMOD, m_regs->SMODE1.EX, m_regs->SMODE1.GCONT, m_regs->SMODE1.LC, m_regs->SMODE1.NVCK, m_regs->SMODE1.PCK2, m_regs->SMODE1.PEHS, m_regs->SMODE1.PEVS, m_regs->SMODE1.PHS, m_regs->SMODE1.PRST, m_regs->SMODE1.PVS, m_regs->SMODE1.RC, m_regs->SMODE1.SINT, m_regs->SMODE1.SLCK, m_regs->SMODE1.SLCK2, m_regs->SMODE1.SPML, m_regs->SMODE1.T1248, m_regs->SMODE1.VCKSEL, m_regs->SMODE1.VHP, m_regs->SMODE1.XPCK ); fprintf(s_fp, "SMODE2 INT=%d FFMD=%d DPMS=%d\n", m_regs->SMODE2.INT, m_regs->SMODE2.FFMD, m_regs->SMODE2.DPMS ); fprintf(s_fp, "SRFSH %08x_%08x\n", m_regs->SRFSH.u32[0], m_regs->SRFSH.u32[1] ); fprintf(s_fp, "SYNCH1 %08x_%08x\n", m_regs->SYNCH1.u32[0], m_regs->SYNCH1.u32[1] ); fprintf(s_fp, "SYNCH2 %08x_%08x\n", m_regs->SYNCH2.u32[0], m_regs->SYNCH2.u32[1] ); fprintf(s_fp, "SYNCV %08x_%08x\n", m_regs->SYNCV.u32[0], m_regs->SYNCV.u32[1] ); fprintf(s_fp, "CSR %08x_%08x\n", m_regs->CSR.u32[0], m_regs->CSR.u32[1] ); fflush(s_fp); } /* int draw[8], sum = 0; for(size_t i = 0; i < countof(draw); i++) { draw[i] = m_perfmon.CPU(GSPerfMon::WorkerDraw0 + i); sum += draw[i]; } printf("CPU %d Sync %d W %d %d %d %d %d %d %d %d (%d)\n", m_perfmon.CPU(GSPerfMon::Main), m_perfmon.CPU(GSPerfMon::Sync), draw[0], draw[1], draw[2], draw[3], draw[4], draw[5], draw[6], draw[7], sum); // */ GSRenderer::VSync(field); m_tc->IncAge(); // if((m_perfmon.GetFrame() & 255) == 0) m_rl->PrintStats(); }
void AbandonShip (ELEMENT *ShipPtr, ELEMENT *TargetPtr, COUNT crew_loss) { SIZE dx, dy; COUNT direction; RECT r; STARSHIP *StarShipPtr; HELEMENT hCrew; INTERSECT_CONTROL ShipIntersect; GetElementStarShip (ShipPtr, &StarShipPtr); if (StarShipPtr->RaceDescPtr->ship_info.ship_flags & CREW_IMMUNE) return; ShipIntersect = ShipPtr->IntersectControl; GetFrameRect (ShipIntersect.IntersectStamp.frame, &r); if ((direction = GetVelocityTravelAngle ( &ShipPtr->velocity)) == FULL_CIRCLE) dx = dy = 0; else { #define MORE_THAN_ENOUGH 100 direction += HALF_CIRCLE; dx = COSINE (direction, MORE_THAN_ENOUGH); dy = SINE (direction, MORE_THAN_ENOUGH); } while (crew_loss-- && (hCrew = AllocElement ())) { #define CREW_LIFE 300 ELEMENT *CrewPtr; DeltaCrew (ShipPtr, -1); PutElement (hCrew); LockElement (hCrew, &CrewPtr); CrewPtr->playerNr = NEUTRAL_PLAYER_NUM; CrewPtr->hit_points = 1; CrewPtr->state_flags = APPEARING | FINITE_LIFE | CREW_OBJECT; CrewPtr->life_span = CREW_LIFE; SetPrimType (&DisplayArray[CrewPtr->PrimIndex], POINT_PRIM); SetPrimColor (&DisplayArray[CrewPtr->PrimIndex], BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x00), 0x02)); CrewPtr->current.image.frame = DecFrameIndex (stars_in_space); CrewPtr->current.image.farray = &stars_in_space; CrewPtr->preprocess_func = crew_preprocess; CrewPtr->collision_func = crew_collision; SetElementStarShip (CrewPtr, StarShipPtr); GetElementStarShip (TargetPtr, &StarShipPtr); CrewPtr->hTarget = StarShipPtr->hShip; { SIZE w, h; INTERSECT_CONTROL CrewIntersect; ShipIntersect.IntersectStamp.origin = ShipPtr->IntersectControl.EndPoint; w = (SIZE)((COUNT)TFB_Random () % r.extent.width); h = (SIZE)((COUNT)TFB_Random () % r.extent.height); CrewIntersect.EndPoint = ShipIntersect.EndPoint; CrewIntersect.IntersectStamp.frame = DecFrameIndex (stars_in_space); if (dx == 0 && dy == 0) { CrewIntersect.EndPoint.x += w - (r.extent.width >> 1); CrewIntersect.EndPoint.y += h - (r.extent.height >> 1); CrewIntersect.IntersectStamp.origin = TargetPtr->IntersectControl.EndPoint; } else { if (dx == 0) CrewIntersect.EndPoint.x += w - (r.extent.width >> 1); else if (dx > 0) CrewIntersect.EndPoint.x += w; else CrewIntersect.EndPoint.x -= w; if (dy == 0) CrewIntersect.EndPoint.y += h - (r.extent.height >> 1); else if (dy > 0)