forked from Ports/goldeneye-pc-port
Merge main into feat/d216-skip-intro (M-84 + D215 findings rows)
# Conflicts: # docs/dev/QOL-INVENTORY.md # docs/dev/findings-index.csv # docs/dev/findings.md # port/src/video.c
This commit is contained in:
commit
208fcfe27d
14 files changed
+343
-29
No files matched your search
@@ -715,7 +715,33 @@ Gfx *viSetupCurrentPlayerView(Gfx *gdl)
|
||||
|
||||
// Create both a floating-point matrix for the CPU side and a fixed-point matrix for the RSP.
|
||||
g_viProjectionMatrix = dynAllocateMatrix();
|
||||
#ifdef PORT
|
||||
/* D211: Video.FovScale — widen the render FOV here, at the one per-frame
|
||||
* chokepoint that feeds both the world (via the CPU-combined proj x view
|
||||
* matrix) and the sky/full-screen layer. fovy is in degrees, so an
|
||||
* angle-proportional scale (portFovScale, default 1.0f) matches the
|
||||
* documented 60deg->75deg at 1.25. Composes with the per-frame aim-zoom
|
||||
* rewrites of fovy for free. NOTE: currentPlayerSetCameraScale() keeps
|
||||
* the nominal FOV for frustum-cull / screen<->world math, so at large
|
||||
* scales edge geometry can cull a hair early — acceptable for a cosmetic
|
||||
* widen. Default 1.0f => identical matrix, bit for bit. */
|
||||
{
|
||||
extern f32 portFovScale;
|
||||
extern s32 lvlGetCurrentStageToLoad(void);
|
||||
f32 frFovY = g_ViBackData->fovy;
|
||||
/* Gameplay only: the front end (main menu / file / mission select /
|
||||
* briefing) also renders through this path with stage == LEVELID_TITLE
|
||||
* (lv.c lvlRender), and the menu 3D is authored at a fixed FOV. */
|
||||
if (portFovScale > 0.4f && portFovScale < 2.01f && portFovScale != 1.0f
|
||||
&& lvlGetCurrentStageToLoad() != LEVELID_TITLE) {
|
||||
frFovY *= portFovScale;
|
||||
if (frFovY > 160.0f) { frFovY = 160.0f; }
|
||||
}
|
||||
guPerspectiveF(g_viProjectionMatrixF, &g_viPerspNorm, frFovY, g_ViBackData->aspect, g_ViBackData->znear, g_ViBackData->zfar, 1.0f);
|
||||
}
|
||||
#else
|
||||
guPerspectiveF(g_viProjectionMatrixF, &g_viPerspNorm, g_ViBackData->fovy, g_ViBackData->aspect, g_ViBackData->znear, g_ViBackData->zfar, 1.0f);
|
||||
#endif
|
||||
guMtxF2L(g_viProjectionMatrixF, g_viProjectionMatrix);
|
||||
|
||||
/**
|
||||
|
||||
+85
-1
@@ -38,6 +38,8 @@
|
||||
#include "gbi_extension.h"
|
||||
|
||||
#ifdef PORT
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
/* D102: the 1P weapon Model and its RW-data pool were punned onto
|
||||
* hand->field_B68 / hand->modeldatas; on x86-64 struct Model (0xE8) is too
|
||||
* big for that layout and modelInit() aliases objinst->datas onto the pool
|
||||
@@ -607,6 +609,47 @@ void gunUpdateAndFire(GUNHAND handnum)
|
||||
hand->field_87F = 0;
|
||||
}
|
||||
|
||||
#ifdef PORT
|
||||
/* GE_DVM=1 — triage the missing 1P weapon viewmodel (D115 item #5 /
|
||||
* docs/dev/VIEWMODEL-RESEARCH.md). One BUNKER1 run with a pistol in hand
|
||||
* dumps the field_87F show/hide gate terms + the model-setup pointers,
|
||||
* rate-limited ~1/s per hand. Env-gated, zero behaviour change.
|
||||
* 87F==0 with gunHwoi==0 -> suspect #1 (Gun_hand_without_item gate;
|
||||
* inv/hitem/f2A44 show which term diverged)
|
||||
* 87F!=0 but numRec > 192 -> suspect #2 (RW pool overrun)
|
||||
* 87F!=0 but RootNode NULL/wild -> suspect #3 (stale copy_of_body_obj_header)
|
||||
* 87F!=0, RootNode sane -> defect is downstream in subdraw/drawjointlist */
|
||||
{
|
||||
static int dvm = -1;
|
||||
static u32 dvm_last[2] = {0, 0};
|
||||
if (dvm < 0) dvm = getenv("GE_DVM") != NULL;
|
||||
if (dvm && handnum < 2) {
|
||||
u32 now = (u32)(osGetTime() / 1000000);
|
||||
if (now != dvm_last[handnum]) {
|
||||
struct player *pl = g_CurrentPlayer;
|
||||
ModelFileHeader *dh = &pl->copy_of_body_obj_header[handnum];
|
||||
dvm_last[handnum] = now;
|
||||
fprintf(stderr,
|
||||
"[DVM] hand=%d item=%d 87F=%d | hdrLine=%d showFP=%d hideHand=%d "
|
||||
"actState=%d ittype=%d ammo=%d | gunHwoi=%d inv=%d hitem=%d f2A44=%d\n",
|
||||
handnum, item, (s32)hand->field_87F,
|
||||
get_ptr_weapon_model_header_line(item) != 0,
|
||||
bondwalkItemCheckBitflags(item, WEAPONSTATBITFLAG_SHOW_FIRST_PERSON),
|
||||
bondwalkItemCheckBitflags(item, WEAPONSTATBITFLAG_HIDE_FIRST_PERSON_HAND),
|
||||
(s32)hand->weapon_action_state, get_itemtype_in_hand(handnum),
|
||||
(s32)hand->weapon_ammo_in_magazine,
|
||||
Gun_hand_without_item(handnum),
|
||||
pl->hand_invisible[handnum], (s32)pl->hand_item[handnum],
|
||||
(s32)pl->field_2A44[handnum]);
|
||||
fprintf(stderr,
|
||||
"[DVM] hdr=%p RootNode=%p Skeleton=%p Switches=%p numMtx=%d numRec=%d (pool=192 words)\n",
|
||||
(void *)dh, (void *)dh->RootNode, (void *)dh->Skeleton,
|
||||
(void *)dh->Switches, (s32)dh->numMatrices, (s32)dh->numRecords);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (hand->field_87F != 0)
|
||||
{
|
||||
mdlhdr = &g_CurrentPlayer->copy_of_body_obj_header[handnum];
|
||||
@@ -1528,7 +1571,26 @@ void gunRenderFirstPersonGunModels(Gfx **gdlptr)
|
||||
s32 handnum;
|
||||
Model *model;
|
||||
|
||||
#ifdef PORT
|
||||
/* D215: the N64 read `renderdata = *(ModelRenderData *)&D_80035CC0;` is a
|
||||
* reinterpret across three separately-declared adjacent .data globals —
|
||||
* `u32 D_80035CC0 = 0;` immediately followed by
|
||||
* `u32 D_80035CC4[] = {1, 3, 0, 0, ...};` (see gun.c) — so on N64 it yields
|
||||
* exactly { basemtx=0, zbufferenabled=1, flags=3, everything-else=0 }.
|
||||
* On x86-64 it breaks twice over: `ModelRenderData`'s pointer members
|
||||
* (`basemtx`, `gdl`, `mtxlist`) widen 4->8 B so `flags` is no longer at
|
||||
* struct offset 8, and the C standard does not guarantee those two globals
|
||||
* are laid out adjacently or in declaration order. Measured result:
|
||||
* `renderdata.flags == 0`, which gates every 1P weapon-model DL node off in
|
||||
* `modelRenderNodeGundl` (`flags & 1`) — the whole "no gun visible while
|
||||
* playing" bug. Reproduce the N64 field values directly. ABI/layout only
|
||||
* (D3x class), no logic change. */
|
||||
renderdata = (ModelRenderData){0};
|
||||
renderdata.zbufferenabled = TRUE;
|
||||
renderdata.flags = 3;
|
||||
#else
|
||||
renderdata = *(ModelRenderData *)&D_80035CC0;
|
||||
#endif
|
||||
|
||||
for (handnum = 0; handnum != 2; handnum++)
|
||||
{
|
||||
@@ -1612,9 +1674,31 @@ void gunRenderFirstPersonGunModels(Gfx **gdlptr)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PORT
|
||||
/* GE_DVM=1: D215 verification probe — how many gfx commands the 1P
|
||||
* weapon model's subdraw() actually emits. Pre-fix this was 1 (just the
|
||||
* gSPSegment); a healthy weapon DL is ~150. Rate-limited ~1/s/hand. */
|
||||
Gfx *dvm_before = renderdata.gdl;
|
||||
#endif
|
||||
subdraw(&renderdata, HAND_WEAPON_MODEL(handptr));
|
||||
gdl = renderdata.gdl;
|
||||
|
||||
#ifdef PORT
|
||||
{
|
||||
static int dvmr = -1;
|
||||
static u32 dvmr_last[2] = {0, 0};
|
||||
if (dvmr < 0) dvmr = getenv("GE_DVM") != NULL;
|
||||
if (dvmr && handnum < 2) {
|
||||
u32 now = (u32)(osGetTime() / 1000000);
|
||||
if (now != dvmr_last[handnum]) {
|
||||
dvmr_last[handnum] = now;
|
||||
fprintf(stderr, "[DVMr] hand=%d item=%d 87F=%d cmds_emitted=%ld cull=%d\n",
|
||||
handnum, item, (s32)handptr->field_87F,
|
||||
(long)(renderdata.gdl - dvm_before), renderdata.cullmode);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bondwalkItemCheckBitflags(item, WEAPONSTATBITFLAG_MIRROR_DUAL) != 0)
|
||||
{
|
||||
gSPClearGeometryMode(gdl++, G_CULL_BOTH);
|
||||
|
||||
Reference in new issue
Block a user