Weapon visuals + aim: beams render from the guns; pick self-target fixes

Renderer (dpl3-revive/patha):
- Instance visibility honored at DRAW time (stored word 4 = live
  dpl_SetInstanceVisibility field): laser beams (4-frame pulses) and
  missile models now render; cache tags w3 0/1 instances 'gated'
- PSFX world bursts (dcs=0 muzzle/impact/explosion) rendered; psfx
  storage list-based so one-shot bursts stop collapsing onto one key
- fix_degenerate applied to INSTANCE chains (was camera-only): the
  beam chain rides four rank-2 rig DCSs; composed rank-2 drew beams
  away from the guns. Offline f1635 now shows both arm beams
  converging on the aim point
- First-person canopy cull: the always-armed cockpit model at the
  head drew as a vertical line down screen center (user-confirmed
  fixed live)

Device (vpx-device/vpxlog.cpp):
- CAM backchannel on the fifosock: bridge streams its validated
  camera (+ vehicle root DCS); raycast_pick aims along the player's
  real look instead of the static view-node pose, which had locked
  every missile/beam onto one fixed wrong world point
- raycast_pick skips hidden-until-armed instances and the player's
  own articulation subtree: picking own beams created a target
  feedback loop, picking own missiles retargeted salvos mid-flight,
  and a picked missile's deleted DCS froze the game (arena2 crash)

Sound (vpx-device/vweawe.cpp): stereo-linked peak limiter replaces
the hard output clamp (the "generator out" crackle); VWE_AWE_LOG
reports pre-limit peaks + duck counts, enabled in launch_pod.ps1.
Missile-fire crackle persists: per-voice EMU8000 clamp suspected.

Eggs/confs: TESTAR2.EGG + gauge_arena2_sound.conf (map=arena2 city
variant); cavern.egg (console-era reference); plasma display on COM2
in the gauge confs; gauge_arena_net_sound.conf (slirp net stack).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-08 00:09:03 -05:00
co-authored by Claude Fable 5
parent 2bb2ff7302
commit cbf7015620
16 changed files with 830 additions and 167 deletions
+2 -2
View File
@@ -10,7 +10,7 @@ cputype=pentium
cycles=max
[serial]
serial1=directserial realport:COM1 rxpollus:100 rxburst:16
serial2=disabled
serial2=directserial realport:COM2
[autoexec]
mount c "C:\VWE\TeslaRel410\ALPHA_1"
c:
@@ -20,7 +20,7 @@ set BLASTER=A220 I5 D1 H5 P330 T6
set TEMP=c:\
set HEAPSIZE=15000000
set L4GAUGE=640x480x16
call setenv.bat r s n g
call setenv.bat r s n p
32rtm.exe -x
btl4opt.exe -egg testarn.egg
32rtm.exe -u
@@ -0,0 +1,57 @@
[sdl]
output=opengl
# higher,higher not highest: HIGH_PRIORITY_CLASS starved the host desktop;
# with the retry patches a rare dropout self-recovers (see gauge_rio.conf).
priority=higher,higher
[dosbox]
memsize=32
machine=svga_s3
[cpu]
core=dynamic
cputype=pentium
cycles=max
[sblaster]
sbtype=sb16
sbbase=220
irq=5
dma=1
hdma=5
[mixer]
# match the EMU8000s' native rate (no resample) and buffer ~60ms so brief
# emulation-thread stalls (RIO retry recovery) don't audibly chop
rate=44100
blocksize=1024
prebuffer=60
[serial]
# RIO on COM1 with the low-latency options (rxpollus/rxburst) so the board's
# few-ms ACK deadline is met; plasma display on COM2 (real pod has both).
serial1=directserial realport:COM1 rxpollus:100 rxburst:16
serial2=directserial realport:COM2
[autoexec]
mount c "C:\VWE\TeslaRel410\ALPHA_1"
c:
cd \REL410\BT
set VIDEOFORMAT=svga
rem production pod card init (PARAMETR.BAT:181-186): DIAGNOSE + AWEUTIL per
rem card -- AWEUTIL /S does the EMU8000 bring-up and DRAM detect the HMI SOS
rem driver relies on; skipping it left the cards uninitialized (silent).
rem aweutil /s SKIPPED for now: it verifies the AWE32 GM ROM, which the
rem emulated cards lack (hangs in a retry loop) -- restore once the ROM is
rem dumped from a real card. diagnose /s kept (passes, sets mixer config).
set BLASTER=A220 I5 D1 H5 P330 T6
c:\sb16\diagnose /s
set BLASTER=A240 I7 D3 H6 P300 T6
c:\sb16\diagnose /s
set BLASTER=A220 I5 D1 H5 P330 T6
set TEMP=c:\
rem arena2 STADIUM mission (TESTAR2.EGG: map=arena2, time=day - the walled arena) with the RIO
rem attached; stdout redirected so mission-load progress survives kills.
set HEAPSIZE=15000000
set L4GAUGE=640x480x16
call setenv.bat r s s p
32rtm.exe -x
btl4opt.exe -egg testar2.egg
32rtm.exe -u
echo ALPHA1-RUN-DONE
pause
@@ -0,0 +1,77 @@
[sdl]
output=opengl
# higher,higher not highest: HIGH_PRIORITY_CLASS starved the host desktop;
# with the retry patches a rare dropout self-recovers (see gauge_rio.conf).
priority=higher,higher
[dosbox]
memsize=32
machine=svga_s3
[cpu]
core=dynamic
cputype=pentium
cycles=max
[sblaster]
sbtype=sb16
sbbase=220
irq=5
dma=1
hdma=5
[mixer]
# match the EMU8000s' native rate (no resample) and buffer ~60ms so brief
# emulation-thread stalls (RIO retry recovery) don't audibly chop
rate=44100
blocksize=1024
prebuffer=60
[ne2000]
# real pods loaded the ODI stack in AUTOEXEC before ANY game launch --
# weapons-fire test: bare -egg run WITH the packet stack resident (the game's
# WATTCP identity is 200.0.0.113 from REL410\BT\WATTCP.CFG). nicbase 340:
# 300 clashes with the VDB and blanks heads. backend=slirp: THIS build lacks
# pcap ("Backend not supported"); slirp = user-mode NAT, no LAN peers, but
# the packet driver functions and accepts sends -- enough for a solo fire
# test. For pod<->console runs use a pcap-enabled build (net_full.conf).
ne2000=true
nicbase=340
nicirq=3
backend=slirp
[serial]
# RIO on COM1 with the low-latency options (rxpollus/rxburst) so the board's
# few-ms ACK deadline is met; plasma display on COM2 (real pod has both).
serial1=directserial realport:COM1 rxpollus:100 rxburst:16
serial2=directserial realport:COM2
[autoexec]
mount c "C:\VWE\TeslaRel410\ALPHA_1"
mount d "C:\VWE\TeslaRel410\emulator\net-boot"
d:
echo === loading NE2000 packet-driver stack (as production AUTOEXEC did) ===
d:\lsl
d:\ne2000
d:\odipkt
c:
cd \REL410\BT
set VIDEOFORMAT=svga
rem production pod card init (PARAMETR.BAT:181-186): DIAGNOSE + AWEUTIL per
rem card -- AWEUTIL /S does the EMU8000 bring-up and DRAM detect the HMI SOS
rem driver relies on; skipping it left the cards uninitialized (silent).
rem aweutil /s SKIPPED for now: it verifies the AWE32 GM ROM, which the
rem emulated cards lack (hangs in a retry loop) -- restore once the ROM is
rem dumped from a real card. diagnose /s kept (passes, sets mixer config).
set BLASTER=A220 I5 D1 H5 P330 T6
c:\sb16\diagnose /s
set BLASTER=A240 I7 D3 H6 P300 T6
c:\sb16\diagnose /s
set BLASTER=A220 I5 D1 H5 P330 T6
set TEMP=c:\
rem arena1 city mission (TESTARN.EGG: map=arena1, time=day), RIO attached,
rem bare -egg launch (no netnub) = the user's real-world test-egg setup.
set HEAPSIZE=15000000
set L4GAUGE=640x480x16
call setenv.bat r s s p
32rtm.exe -x
rem stdout -> log: this optimized build still emits DEBUG_STREAM lines (the
rem RIO retry spam proved it) -- capture the weapon fire-refusal reason.
rem DOS flushes in 4KB chunks; the tail lands on clean exit (mission timer).
btl4opt.exe -egg testarn.egg > c:\weaponlog.txt
32rtm.exe -u
echo ALPHA1-RUN-DONE
pause
@@ -24,9 +24,9 @@ blocksize=1024
prebuffer=60
[serial]
# RIO on COM1 with the low-latency options (rxpollus/rxburst) so the board's
# few-ms ACK deadline is met; plasma COM2 later.
# few-ms ACK deadline is met; plasma display on COM2 (real pod has both).
serial1=directserial realport:COM1 rxpollus:100 rxburst:16
serial2=disabled
serial2=directserial realport:COM2
[autoexec]
mount c "C:\VWE\TeslaRel410\ALPHA_1"
c:
@@ -48,7 +48,7 @@ rem arena1 city mission (TESTARN.EGG: map=arena1, time=day) with the RIO
rem attached; stdout redirected so mission-load progress survives kills.
set HEAPSIZE=15000000
set L4GAUGE=640x480x16
call setenv.bat r s s g
call setenv.bat r s s p
32rtm.exe -x
btl4opt.exe -egg testarn.egg
32rtm.exe -u
+1
View File
@@ -57,6 +57,7 @@ if ($NoSound) {
} else {
$env:VWE_AWE32 = '1'
$env:VWE_AWE_ROM = (Resolve-Path "$PSScriptRoot\..\roms\awe32.raw").Path
$env:VWE_AWE_LOG = '1' # 10s reports incl. limiter stats (crackle diagnosis)
}
$dosbox = (Resolve-Path "$PSScriptRoot\..\src\src\dosbox-x.exe").Path
+22
View File
@@ -85,6 +85,7 @@ def fp_cam(board, cache):
h = max(anim, key=lambda k: float(np.abs(np.array(anim[k][9:12])).sum()))
if h is None:
return None
fp_cam.root = h # player vehicle root DCS (for the pick backchannel)
f = anim[h]
R = np.array(f[:9]).reshape(3, 3)
t = np.array(f[9:12])
@@ -145,6 +146,26 @@ def fp_cam(board, cache):
M[0, :3], M[1, :3], M[2, :3], M[3, :3] = right, up, back, eye
return M
def send_cam(M):
# Backchannel on the fifosock: hand the device OUR camera (the
# user-validated cockpit view, twist + glance included) so its reticle
# raycast aims where the player actually looks. The device's own view
# decode sits at the static view-node pose, which aimed every pick --
# and thus every missile volley and laser beam -- at one fixed wrong
# world point (the "missiles fly off to a fixed spot" bug).
if sock is None:
return
eye, fwd = M[3, :3], -M[2, :3]
# 7th field: player vehicle root DCS -- the device skips instances on
# this articulation subtree (own arms/torso/muzzle-flash), which the ray
# grazes intermittently and which retargeted mid-volley missiles.
root = getattr(fp_cam, 'root', 0) or 0
try:
sock.send(f"CAM {eye[0]:.3f} {eye[1]:.3f} {eye[2]:.3f} "
f"{fwd[0]:.6f} {fwd[1]:.6f} {fwd[2]:.6f} {root:x}\n".encode())
except OSError:
pass
def render(board):
try:
pg = r.pygame
@@ -161,6 +182,7 @@ def render(board):
M = fp_cam(board, r.cache)
if M is not None:
r.cam_matrix = lambda _b, _M=M: _M
send_cam(M)
r.draw(board)
except KeyboardInterrupt:
raise