Gitea #44: the reticle TARGET NAME PLATE (PNAME1-8) -- the target's callsign under the crosshair
Reconstructed the last deferred piece of the 1995 reticle, decoded from the Execute disassembly @004cdcf0 [T1]: - selection: target_mech+0x190 (owning BTPlayer) -> player+0x1e0 (playerBitmapIndex), 1-based into the mesh table at this+0x2e8 - placement: re-placed every frame the aim moves -- scale 0.12 uniform, translate (K*retPos.x, K*retPos.y - 0.08, -1.0), K = 1/2.8 (the x87 long double @0x4cee64) -- so the label TRACKS THE AIM POINT, not screen centre - visibility: the LOCK attribute (this+0x184, cached +0x188) AND an owning player; reticle-off / simple-X also hide it - art: the plate quad UV-addresses a shared 128x64 bitslice texmap whose texels the pod OVERWROTE each mission with the egg's callsign rasters (original source commented out at L4VIDEO.cpp:5682-5710) -- the baked 'PLAYER n' art in BMAP.BSL is only the shipped fallback. Material colour is a neutral (0.5,0.5,0.5): grey-white, not phosphor green. Port: same geometry in reticle units (0.224 below the aim point, 0.336x0.084) drawn as the target's egg callsign texture through the reticle's own MapX/MapY mapping, so it follows the world view in every layout and BT_SHOT captures it. New: dpl2d_DrawTexturedRect, BTReticleTargetPlate, BTGetPlayerNameTexture. Also: kRetCaret corrected 0.02f -> 0.025f (_DAT_004cd7f4 read from the binary; the old value was a T3 guess, 20% small). KB: gauges-hud + open-questions corrected (the chain was filed as deferred and mis-attributed to 'the 3D marker'); TWO PNAME consumers now distinguished (this plate, and CameraShipHUDRenderable's ranking window which shipped 2026-07-18); new bgf-format section on the plate atlas. Rig-verified: 2-node relay, BT_GOTO=enemy -> '[hud] name plate: bmp=2 tex=1' and 'Boreas' rendered under the crosshair on the locked target. Solo clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0166KTsC7ADm7VXEi1HF1jNg
This commit is contained in:
co-authored by
Claude Opus 5
parent
b7107b1020
commit
35c750dc7c
@@ -572,3 +572,108 @@ void dpl2d_ExecuteList(dpl2d_DISPLAY *list, IDirect3DDevice9 *device)
|
||||
device->SetRenderState(D3DRS_SRCBLEND, oldSrc);
|
||||
device->SetRenderState(D3DRS_DESTBLEND, oldDst);
|
||||
}
|
||||
|
||||
//
|
||||
//#############################################################################
|
||||
// dpl2d_DrawTexturedRect -- a TEXTURED quad in RETICLE coordinates
|
||||
//#############################################################################
|
||||
//
|
||||
// The reticle's target NAME PLATE (the 1995 PNAMEx.bgf plate) is a UV-mapped
|
||||
// quad, so it cannot ride the line/polyline display lists above -- but it must
|
||||
// land in the SAME space, because the binary places it from the same
|
||||
// `Reticle::reticlePosition` that translates the aim group (reticle Execute
|
||||
// @004cdede [T1 disasm]). So it reuses this TU's authentic mapping: MapX's
|
||||
// aspect-corrected x unit + MapY's half-height y unit, in the CURRENT viewport
|
||||
// (which is the world sub-rect under the cockpit-surround layout, not the whole
|
||||
// backbuffer -- so the plate follows the view like the rest of the reticle).
|
||||
//
|
||||
// cx/cy = quad CENTRE, w/h = full extents, all in reticle units. The texture
|
||||
// arrives as void* because the caller (game/reconstructed/btl4vid.cpp) carries
|
||||
// no d3d9 types. State is saved/restored exactly as dpl2d_ExecuteList does
|
||||
// (leaking a texture stage or the alpha state into the next frame's 3D pass is
|
||||
// the "floating rocks" class of bug).
|
||||
//
|
||||
void dpl2d_DrawTexturedRect(
|
||||
IDirect3DDevice9 *device,
|
||||
void *texture,
|
||||
float cx,
|
||||
float cy,
|
||||
float w,
|
||||
float h,
|
||||
unsigned long argb)
|
||||
{
|
||||
if (device == 0 || texture == 0)
|
||||
return;
|
||||
|
||||
D3DVIEWPORT9 vp;
|
||||
if (FAILED(device->GetViewport(&vp)))
|
||||
return;
|
||||
|
||||
const float ox = (float)vp.X, oy = (float)vp.Y;
|
||||
const float vw = (float)vp.Width, vh = (float)vp.Height;
|
||||
const float xunit = XUnit(vw, vh); // aspect-corrected, as MapX
|
||||
const float yunit = vh * 0.5f; // as MapY
|
||||
|
||||
const float px = MapX(cx, ox, vw, vh);
|
||||
const float py = MapY(cy, oy, vh);
|
||||
const float hw = (w * 0.5f) * xunit;
|
||||
const float hh = (h * 0.5f) * yunit;
|
||||
|
||||
struct VertexTex
|
||||
{
|
||||
float x, y, z, rhw;
|
||||
DWORD color;
|
||||
float u, v;
|
||||
};
|
||||
const DWORD kVertexTexFVF =
|
||||
(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
|
||||
|
||||
VertexTex quad[4];
|
||||
memset(quad, 0, sizeof(quad));
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
quad[i].z = 0.0f;
|
||||
quad[i].rhw = 1.0f;
|
||||
quad[i].color = (DWORD)argb; // modulates the plate art (its material colour)
|
||||
}
|
||||
// tri-strip order: TR, TL, BR, BL
|
||||
quad[0].x = px + hw; quad[0].y = py - hh; quad[0].u = 1.0f; quad[0].v = 0.0f;
|
||||
quad[1].x = px - hw; quad[1].y = py - hh; quad[1].u = 0.0f; quad[1].v = 0.0f;
|
||||
quad[2].x = px + hw; quad[2].y = py + hh; quad[2].u = 1.0f; quad[2].v = 1.0f;
|
||||
quad[3].x = px - hw; quad[3].y = py + hh; quad[3].u = 0.0f; quad[3].v = 1.0f;
|
||||
|
||||
DWORD oldLighting = 0, oldZ = 0, oldCull = 0;
|
||||
DWORD oldAlpha = 0, oldSrc = 0, oldDst = 0, oldFog = 0;
|
||||
device->GetRenderState(D3DRS_LIGHTING, &oldLighting);
|
||||
device->GetRenderState(D3DRS_ZENABLE, &oldZ);
|
||||
device->GetRenderState(D3DRS_CULLMODE, &oldCull);
|
||||
device->GetRenderState(D3DRS_ALPHABLENDENABLE, &oldAlpha);
|
||||
device->GetRenderState(D3DRS_SRCBLEND, &oldSrc);
|
||||
device->GetRenderState(D3DRS_DESTBLEND, &oldDst);
|
||||
device->GetRenderState(D3DRS_FOGENABLE, &oldFog);
|
||||
IDirect3DBaseTexture9 *oldTex = 0;
|
||||
device->GetTexture(0, &oldTex);
|
||||
|
||||
device->SetRenderState(D3DRS_LIGHTING, FALSE);
|
||||
device->SetRenderState(D3DRS_ZENABLE, FALSE);
|
||||
device->SetRenderState(D3DRS_FOGENABLE, FALSE);
|
||||
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
device->SetFVF(kVertexTexFVF);
|
||||
device->SetTexture(0, (IDirect3DTexture9 *)texture);
|
||||
|
||||
device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(VertexTex));
|
||||
|
||||
device->SetTexture(0, oldTex);
|
||||
if (oldTex) oldTex->Release();
|
||||
device->SetFVF(kVertex2DFVF);
|
||||
device->SetRenderState(D3DRS_LIGHTING, oldLighting);
|
||||
device->SetRenderState(D3DRS_ZENABLE, oldZ);
|
||||
device->SetRenderState(D3DRS_FOGENABLE, oldFog);
|
||||
device->SetRenderState(D3DRS_CULLMODE, oldCull);
|
||||
device->SetRenderState(D3DRS_ALPHABLENDENABLE, oldAlpha);
|
||||
device->SetRenderState(D3DRS_SRCBLEND, oldSrc);
|
||||
device->SetRenderState(D3DRS_DESTBLEND, oldDst);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user