mirror of
https://github.com/jkdansereau/goldeneye-pc-port.git
synced 2026-10-23 15:52:42 +02:00
D320/D288: extend GE_D318T with generic pin detector; refine GE_D288 probe; cache bg.c hot-path getenvs
D320 (Phase 1 item 1): d318TimelineTick (GE_D318T=1) now also runs a generic D318-class pin DETECTOR for the sweep's flagged lists (Facility ai_19, Control ai_9, Depot ai_12): any chr in ACT_ATTACK with a live-fire attacktype (no TARGET_AIM_ONLY bit) whose modelGetAnimFrame is byte-stable for 600 ticks logs one 'D320T: PIN?' line with AI-list id/offset/atk/ent/ mot/unk54, repeating every further 600 stable ticks. Detection only -- the recovery watchdog stays hardcoded to ai_22 by design (D320's explicit instruction: generalize only after a second list actually freezes in play). Legit states excluded/self-clearing: monologue pre-aims keep the AIM_ONLY bit; working fire cycles re-init through chrlvTickAttackCommon so their frame does not stay byte-stable for 10 s. Smoke: 90 s Facility run, zero false positives, existing D318T timeline unaffected. D288 (Phase 1 item 3): per M-155's revised next step, the GE_D288 probe now skips any_behind_camera==1 triangles (the x/w divide is meaningless for w<=0 -- that subset was pure false-lead noise) and logs the render-mode word (oml) so a live capture can ID the culprit asset against level tables. Re-ran bare -level_20: 1965 sane hits in the 550-755 window, still zero hits for the target color RGB(83,62,44) -- consistent with M-155's working theory that the bare boot's scripted camera never reaches the bug state; headless probing is at its limit here, live capture is next. bg.c getenv caching (D302-class sweep follow-up): GE_D104 (per room pass, per frame), GE_D63 primary+secondary render logs (per room, per frame), and the two GE_D154 inner-GDL-walk sites (per bullet hit) now use the cached static pattern. All #ifdef PORT blocks; zero behavior change when unset.
This commit is contained in:
1 parent
56ac2ab870
commit
8d3bd5732a
3 files changed
+164
-21
No files matched your search
+26
-16
@@ -1761,23 +1761,32 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx, bo
|
||||
return;
|
||||
}
|
||||
|
||||
/* D288 diag (M-152, frame-gated M-155): the silo intro's
|
||||
* screen-filling stray triangle (bounded to level_20 frames
|
||||
* ~562-741) isn't explained by this function's existing D233/D106
|
||||
* guards on static review -- log any triangle whose clip-space NDC
|
||||
* bbox covers an unreasonable chunk of the screen, or whose bbox
|
||||
* math goes non-finite, together with each vertex's w and
|
||||
* any_behind_camera, to catch it at draw time. M-155: the first
|
||||
* ungated run fired 116k times in ~1500-2000 frames -- bbox_frac
|
||||
* >0.15 alone is a common occurrence for ordinary near-camera
|
||||
* geometry, not a distinguishing signature. Gated to the reported
|
||||
* frame window (num_dls, same pattern as GE_D236RM below) and the
|
||||
/* D288 diag (M-152, frame-gated M-155, any_behind-restricted
|
||||
* M-155-follow-up): the silo intro's screen-filling stray triangle
|
||||
* (bounded to level_20 frames ~562-741) isn't explained by this
|
||||
* function's existing D233/D106 guards on static review -- log any
|
||||
* triangle whose clip-space NDC bbox covers an unreasonable chunk
|
||||
* of the screen, together with each vertex's w and the render-mode
|
||||
* word (oml), to catch it at draw time. M-155: the first ungated
|
||||
* run fired 116k times in ~1500-2000 frames -- bbox_frac >0.15
|
||||
* alone is a common occurrence for ordinary near-camera geometry,
|
||||
* not a distinguishing signature. Gated to the reported frame
|
||||
* window (num_dls, same pattern as GE_D236RM below) and the
|
||||
* threshold raised well above the ~0.15 "normal" baseline M-155
|
||||
* established, so a hit here is actually rare. Remove once D288 is
|
||||
* root-caused. */
|
||||
* established, so a hit here is actually rare. M-155 follow-up:
|
||||
* for any_behind_camera==1 triangles the x/w perspective divide is
|
||||
* meaningless (w near zero or negative -> arbitrarily large
|
||||
* "bbox_frac" for perfectly ordinary geometry), which is exactly
|
||||
* why the code above defers those to GL's own clipper -- so the
|
||||
* probe now skips them entirely; a hit here has comfortably
|
||||
* positive w's and is a genuine large-NDC-bbox triangle. oml is
|
||||
* logged so the culprit's material/model can be identified against
|
||||
* the level's asset tables (the flat RGB(83,62,44) color grep
|
||||
* found nothing in the .c sources -- binary model blobs). Remove
|
||||
* once D288 is root-caused. */
|
||||
static int ge_d288 = -1;
|
||||
if (ge_d288 < 0) ge_d288 = getenv("GE_D288") != NULL;
|
||||
if (ge_d288) {
|
||||
if (ge_d288 && !any_behind_camera) {
|
||||
extern uint32_t num_dls;
|
||||
if (num_dls >= 550 && num_dls <= 755) {
|
||||
float minx = std::fmin(std::fmin(v1->x / v1->w, v2->x / v2->w), v3->x / v3->w);
|
||||
@@ -1786,8 +1795,9 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx, bo
|
||||
float maxy = std::fmax(std::fmax(v1->y / v1->w, v2->y / v2->w), v3->y / v3->w);
|
||||
float bbox_frac = (maxx - minx) * (maxy - miny) / 4.0f; // NDC quad is [-1,1]^2
|
||||
if (!std::isfinite(bbox_frac) || bbox_frac > 0.5f) {
|
||||
fprintf(stderr, "D288: dl=%u tri w=(%.6f,%.6f,%.6f) bbox_frac=%.3f any_behind=%d color=(%d,%d,%d)\n",
|
||||
num_dls, v1->w, v2->w, v3->w, bbox_frac, (int)any_behind_camera,
|
||||
fprintf(stderr, "D288: dl=%u tri w=(%.6f,%.6f,%.6f) bbox_frac=%.3f oml=0x%08x color=(%d,%d,%d)\n",
|
||||
num_dls, v1->w, v2->w, v3->w, bbox_frac,
|
||||
(unsigned)rdp.other_mode_l,
|
||||
v1->color.r, v1->color.g, v1->color.b);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,6 +93,10 @@
|
||||
/* chrai.c defines these but chrai.h does not declare them. */
|
||||
extern s32 chraiGetAIListID(AIRecord *AIList, bool *isGlobalAIList);
|
||||
|
||||
/* src/bondaicommands.h:467 -- kept local so this port file doesn't pull in
|
||||
* the AI-command header just for one bit constant. */
|
||||
#define D320_TARGET_AIM_ONLY 0x0020 /* "Aim at target instead of firing" */
|
||||
|
||||
/* chraction.c internal (not in chraction.h): the fresh-attack entry point.
|
||||
* Signature from the definition; call form mirrors chrlvTickAttack's own
|
||||
* re-init at chraction.c:7401. */
|
||||
@@ -434,6 +438,125 @@ void d318TimelineTick(void)
|
||||
(unsigned)(u32)(g_randomSeed >> 32), (unsigned)(u32)g_randomSeed,
|
||||
(unsigned)objectiveregisters1, (unsigned)h, (int)g_ActiveChrsCount);
|
||||
}
|
||||
|
||||
/* D320: generic D318-class pin DETECTION for the sweep's flagged lists
|
||||
* (Facility ai_19, Control ai_9, Depot ai_12 -- see findings D320).
|
||||
* Detection only: it logs, it never intervenes; the recovery watchdog
|
||||
* above stays hardcoded to ai_22 by design until a second list actually
|
||||
* freezes in play (D320's explicit instruction).
|
||||
*
|
||||
* Signature: a chr in ACT_ATTACK whose attacktype is LIVE FIRE (no
|
||||
* TARGET_AIM_ONLY bit -- it is supposed to be shooting) and whose
|
||||
* modelGetAnimFrame is byte-stable for 600 consecutive ticks (10 s). A
|
||||
* guard that should be firing but whose animation never advances is the
|
||||
* exact D318 frozen shape on any list. The two legitimate long-stable
|
||||
* states are excluded or self-clearing: monologue pre-aims keep the
|
||||
* AIM_ONLY bit (excluded), and a working fire cycle re-inits through
|
||||
* chrlvTickAttackCommon's "endframe <= frame" block, so its frame does
|
||||
* not stay byte-stable for 10 s. One line at first detection, then one
|
||||
* per further 600 stable ticks while it persists; a frozen run keeps
|
||||
* printing, an escaped run stops after the single line (or none). */
|
||||
{
|
||||
typedef struct { s16 chrnum; u32 framebits; s32 stable; s32 nextlog; }
|
||||
D320Pin;
|
||||
static D320Pin s_pins[8];
|
||||
static int s_npins = 0;
|
||||
s32 i, j;
|
||||
|
||||
for (i = 0; i < g_ActiveChrsCount; i++)
|
||||
{
|
||||
ChrRecord *c = &g_ActiveChrs[i];
|
||||
union { f32 f; u32 u; } fr;
|
||||
D320Pin *p = NULL;
|
||||
|
||||
if (c->actiontype != ACT_ATTACK || c->model == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if ((s32)c->act_attack.attacktype & D320_TARGET_AIM_ONLY)
|
||||
{
|
||||
continue; /* legitimate hold pose (monologue pre-aim) */
|
||||
}
|
||||
|
||||
fr.f = modelGetAnimFrame(c->model);
|
||||
for (j = 0; j < s_npins; j++)
|
||||
{
|
||||
if (s_pins[j].chrnum == c->chrnum)
|
||||
{
|
||||
p = &s_pins[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!p)
|
||||
{
|
||||
if (s_npins < 8)
|
||||
{
|
||||
p = &s_pins[s_npins++];
|
||||
}
|
||||
else
|
||||
{
|
||||
continue; /* table full: drop the newest, keep tracking */
|
||||
}
|
||||
p->chrnum = c->chrnum;
|
||||
p->framebits = fr.u;
|
||||
p->stable = 0;
|
||||
p->nextlog = 600;
|
||||
}
|
||||
|
||||
if (p->framebits == fr.u)
|
||||
{
|
||||
p->stable++;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->framebits = fr.u;
|
||||
p->stable = 0;
|
||||
p->nextlog = 600;
|
||||
}
|
||||
|
||||
if (p->stable >= p->nextlog)
|
||||
{
|
||||
bool g = FALSE;
|
||||
s32 aid = c->ailist ? chraiGetAIListID(c->ailist, &g) : -1;
|
||||
|
||||
osSyncPrintf("D320T: t=%d PIN? c%d aiid=0x%04x%s off=%d atk=0x%x ent=%d "
|
||||
"mot=%d unk54=%u frame=%.2f stable=%d ticks (D318-class pin candidate)\n",
|
||||
(int)g_GlobalTimer, (int)c->chrnum,
|
||||
(unsigned)aid, g ? "G" : "", (int)c->aioffset,
|
||||
(unsigned)c->act_attack.attacktype,
|
||||
(int)c->act_attack.entityid,
|
||||
(s32)c->act_attack.type_of_motion,
|
||||
(unsigned)c->act_attack.unk54,
|
||||
(double)fr.f, p->stable);
|
||||
p->nextlog = p->stable + 600;
|
||||
}
|
||||
}
|
||||
|
||||
/* Drop entries for chrs that left the tracked state so a later
|
||||
* re-entry starts a fresh confirmation window. */
|
||||
for (i = 0; i < s_npins; i++)
|
||||
{
|
||||
bool alive = FALSE;
|
||||
|
||||
for (j = 0; j < g_ActiveChrsCount; j++)
|
||||
{
|
||||
ChrRecord *c = &g_ActiveChrs[j];
|
||||
|
||||
if (c->chrnum == s_pins[i].chrnum && c->actiontype == ACT_ATTACK
|
||||
&& c->model != NULL
|
||||
&& !((s32)c->act_attack.attacktype & D320_TARGET_AIM_ONLY))
|
||||
{
|
||||
alive = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!alive)
|
||||
{
|
||||
s_pins[i] = s_pins[--s_npins];
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* PORT */
|
||||
+15
-5
@@ -651,7 +651,9 @@ Gfx *sub_GAME_7F0B3C8C(Gfx *gdl)
|
||||
/* TEMP D104: room render-pass geometry-visibility probe. */
|
||||
{
|
||||
static s32 d104c = 0;
|
||||
if (getenv("GE_D104") && (d104c++ % 600) == 0 && d104c < 12000) {
|
||||
static int d104on = -1; /* D302-class cache: this runs per room pass, per frame */
|
||||
if (d104on < 0) d104on = getenv("GE_D104") != NULL;
|
||||
if (d104on && (d104c++ % 600) == 0 && d104c < 12000) {
|
||||
s32 rr;
|
||||
osSyncPrintf("D104 tick=%d curRoom=%d roomsDrawn=%d budget=%d :",
|
||||
d104c, (s32)g_CurrentPlayer->curRoomIndex,
|
||||
@@ -2952,7 +2954,9 @@ Gfx *bgRenderRoomPrimary(Gfx *gdl, s32 room_index)
|
||||
|
||||
#if defined(PORT)
|
||||
/* TEMP D63: log primary GDL at render time (env GE_D63=1) */
|
||||
if (getenv("GE_D63")) {
|
||||
static int d63on_p = -1; /* D302-class cache: per room, per frame */
|
||||
if (d63on_p < 0) d63on_p = getenv("GE_D63") != NULL;
|
||||
if (d63on_p) {
|
||||
u32 *w = (u32 *)g_BgRoomInfo[room_index].ptr_expanded_mapping_info;
|
||||
osSyncPrintf("D63 bgRenderRoomPrimary room=%d ptr=%p usize=%d w0..3=(%08x,%08x,%08x,%08x)\n",
|
||||
room_index, (void *)g_BgRoomInfo[room_index].ptr_expanded_mapping_info,
|
||||
@@ -2997,7 +3001,9 @@ Gfx *bgRenderRoomSecondary(Gfx *gdl, s32 room_index)
|
||||
|
||||
#if defined(PORT)
|
||||
/* TEMP D63: log secondary GDL at render time (env GE_D63=1) */
|
||||
if (getenv("GE_D63")) {
|
||||
static int d63on_s = -1; /* D302-class cache: per room, per frame */
|
||||
if (d63on_s < 0) d63on_s = getenv("GE_D63") != NULL;
|
||||
if (d63on_s) {
|
||||
u32 *w = (u32 *)g_BgRoomInfo[room_index].ptr_secondary_expanded_mapping_info;
|
||||
osSyncPrintf("D63 bgRenderRoomSecondary room=%d ptr=%p usize=%d w0..3=(%08x,%08x,%08x,%08x)\n",
|
||||
room_index, (void *)g_BgRoomInfo[room_index].ptr_secondary_expanded_mapping_info,
|
||||
@@ -3509,7 +3515,9 @@ bool bgTestRayIntersectionInRoom(coord3d *from, coord3d *to, coord3d *dir, RoomV
|
||||
idx[2] = (((u8 *) gdl)[7] / 10) - vtxoff;
|
||||
#endif
|
||||
#ifdef PORT
|
||||
if (getenv("GE_D154"))
|
||||
static int d154on = -1; /* D302-class cache: inner GDL walk, fires per bullet hit */
|
||||
if (d154on < 0) d154on = getenv("GE_D154") != NULL;
|
||||
if (d154on)
|
||||
osSyncPrintf("D154 TRI1 w1=%08x idx=%d,%d,%d\n",
|
||||
(unsigned)(u32)gdl->words.w1, (int)idx[0], (int)idx[1], (int)idx[2]);
|
||||
#endif
|
||||
@@ -3694,7 +3702,9 @@ bool bgTestRayIntersectionInRoom(coord3d *from, coord3d *to, coord3d *dir, RoomV
|
||||
}
|
||||
#endif
|
||||
#ifdef PORT
|
||||
if (getenv("GE_D154"))
|
||||
static int d154on4 = -1; /* D302-class cache: inner GDL walk, fires per bullet hit */
|
||||
if (d154on4 < 0) d154on4 = getenv("GE_D154") != NULL;
|
||||
if (d154on4)
|
||||
osSyncPrintf("D154 TRI4 s2=%d w0=%08x w1=%08x idx2=%d,%d,%d\n",
|
||||
(int)s2, (unsigned)(u32)gdl->words.w0, (unsigned)(u32)gdl->words.w1,
|
||||
(int)idx2[0], (int)idx2[1], (int)idx2[2]);
|
||||
|
||||
Reference in new issue
Block a user