v0.3.0 release review: watchdog re-arm, rule-2 sign-offs, GPL source removal, repo hygiene

Per the 2026-09-19 adversarial pre-ship review (findings.md M-192):

- d318watchdog.c: one-shot per OCCURRENCE, not per process -- re-arm after
  600 ticks of signature absence so a Facility replay in the same session
  (AllUnlocked) is still covered.
- model.c: RULE-2-SIGNOFF records for the retained M-183/M-185 and D311
  defensive clamps (user-approved retention as the stability-maximizing
  option; stale 'Threshold: 50.0' comment corrected to 10.0f; both marked
  post-release removal candidates pending full cutscene re-verification).
- reference/mouse-injector/: removed from the public repo (GPLv2 source +
  prebuilt discord-rpc.lib in an MIT project; never compiled here).
  Provenance stub README remains; path gitignored for local re-vendoring.
  AGENTS.md / GEPD-INPUT-PLAN.md / optionsoverlay.c refs updated.
- scratch/: untracked + gitignored (19 session logs/probe sources were
  committed in the release window).
- findings-index.csv: D317 (and 5 other stale rows) now CLOSED -- added
  CLOSED to gen_findings_index.py's verdict vocabulary.
- docs: D310 perf gauge (no change warranted), GE_DEBUG_UNLOCKALL noted in
  security-and-fidelity-status.md, release notes gain the missing D318
  watchdog bullet + FOV-clamp clarification.

Build verified: ./build-pc.sh ntsc-final clean; gen_findings_index.py
--check and gen_env_probes.py --check pass.
This commit is contained in:
James Dansereau committed 2026-09-20 10:51:12 -04:00
1 parent 63315030f8
commit b3b0ff74db
57 files changed
+157 -11732

No files matched your search

+11 -2
View File
@@ -48,8 +48,10 @@
- **Automatic widescreen FOV scaling**: the game now scales its field of - **Automatic widescreen FOV scaling**: the game now scales its field of
view to match your display's aspect ratio automatically, instead of view to match your display's aspect ratio automatically, instead of
requiring the old manual FOV-scale slider. Toggle off in the F10 overlay requiring the old manual FOV-scale slider. Toggle off in the F10 overlay
(`Widescreen Auto`) if you prefer the original 4:3 framing. (This is FOV (`Widescreen Auto`) if you prefer the original 4:3 framing. The scaled
scaling, not a native 16:9 world/HUD re-render — see Known Issues.) vertical FOV is clamped to a 20°–160° range as a guard against degenerate
values on unusual aspect ratios. (This is FOV scaling, not a native 16:9
world/HUD re-render — see Known Issues.)
- **TV overscan artifacts removed**: the black bars top/bottom and the thin - **TV overscan artifacts removed**: the black bars top/bottom and the thin
pixel strips left/right of the gameplay view are gone (D247/D246) — both pixel strips left/right of the gameplay view are gone (D247/D246) — both
were the original N64 TV-safe-area margin, invisible on a CRT under real were the original N64 TV-safe-area margin, invisible on a CRT under real
@@ -77,6 +79,13 @@
players hit with an identical crash address (GitHub #87, D301) — this players hit with an identical crash address (GitHub #87, D301) — this
should close that crash, though we weren't able to reproduce the exact should close that crash, though we weren't able to reproduce the exact
trigger condition ourselves to confirm it end-to-end. trigger condition ourselves to confirm it end-to-end.
- **Facility's execution softlock is caught and recovered from**: a rare
race in the original game's own AI script (present on the N64 too) could
leave Ourumov frozen mid-execution after Objective C, with no way out short
of reloading. A port-side watchdog now detects the exact unrecoverable
state and re-seeds the attack so the scene plays out as authored; it
re-arms once the scene has cleared, so replaying Facility later in the
same session is still covered (D318).
- **A Steam Deck crash is fixed**: an audio-thread bug could crash the game - **A Steam Deck crash is fixed**: an audio-thread bug could crash the game
early in a level (`sndHandleEvent`'s sound-preemption scan could early in a level (`sndHandleEvent`'s sound-preemption scan could
dereference a pointer without checking it was valid first). Live-verified dereference a pointer without checking it was valid first). Live-verified
+6
View File
@@ -156,6 +156,12 @@ ge007.crash.log
# agent scratch space + audio probe artifacts (regenerable dumps/traces) # agent scratch space + audio probe artifacts (regenerable dumps/traces)
scratchpad/ scratchpad/
# session logs / investigation scratch — local only, never in the public repo
# (untracked 2026-09-19 during the v0.3.0 release review)
/scratch/
# re-vendored GPL reference source (see reference/mouse-injector/README.md)
/reference/mouse-injector/*
!reference/mouse-injector/README.md
# local research/backlog working docs (TCRF cut-content cross-reference etc.) # local research/backlog working docs (TCRF cut-content cross-reference etc.)
backlog/ backlog/
# montage work artifact: the tiled contact sheet behind docs/img/shots/ and # montage work artifact: the tiled contact sheet behind docs/img/shots/ and
+1 -1
View File
@@ -26,7 +26,7 @@
| `port/src/` | Shims: `libultra.c` (OS API), `gesched.c` (scheduler), `n64stubs.c` (boot/TLB/FPU/rmon), `random.c` (PRNG ported verbatim from `random.s`), `ucode.c` (microcode segment markers), `main.c`, `video.c`, … | | `port/src/` | Shims: `libultra.c` (OS API), `gesched.c` (scheduler), `n64stubs.c` (boot/TLB/FPU/rmon), `random.c` (PRNG ported verbatim from `random.s`), `ucode.c` (microcode segment markers), `main.c`, `video.c`, … |
| `port/fast3d/` | Software RSP (adapted from the PD port). The main Phase 2 work. | | `port/fast3d/` | Software RSP (adapted from the PD port). The main Phase 2 work. |
| `rsp/graphics/gmain.s` | GE's RSP ucode — ground truth for GBI/CC/RM. | | `rsp/graphics/gmain.s` | GE's RSP ucode — ground truth for GBI/CC/RM. |
| `reference/mouse-injector/` | Vendored GEPD-Edition Mouse Injector source (GPLv2, read-only reference — never compile or modify). Ground truth for the mouse-aim model: `games/goldeneye.c` is the whole GE aim/hipfire/menu model (our D194 mirror); see its README + `docs/dev/GEPD-INPUT-PLAN.md`. | | `reference/mouse-injector/README.md` | **Stub only** — the vendored GEPD-Edition Mouse Injector source (GPLv2) was removed from the public repo 2026-09-19 (license hygiene: GPL code + prebuilt binary in an MIT project; it was never compiled here). The stub records provenance + how to re-vendor locally (gitignored). The ported mouse-aim model lives in `port/src/input.c` (D194 lineage); design record: `docs/dev/GEPD-INPUT-PLAN.md`. |
| A local **Perfect Dark PC port** checkout ([fgsfdsfgs/perfect_dark](https://github.com/fgsfdsfgs/perfect_dark)) | **Standing reference** — consult it whenever a work item has a PD analogue (same Rare engine family): port-layer ground truth (`port/fast3d/`, crash/system/video), plus copy candidates `port/src/preprocess/` (N64→PC asset conversion; `filemodel.c` is the D43 near-analogue) and `mixer.c`/`input.c`/`fs.c`. Port-layer files only; same family ≠ identical format — validate per field. Full audit: `docs/internals.md` §2.4. | | A local **Perfect Dark PC port** checkout ([fgsfdsfgs/perfect_dark](https://github.com/fgsfdsfgs/perfect_dark)) | **Standing reference** — consult it whenever a work item has a PD analogue (same Rare engine family): port-layer ground truth (`port/fast3d/`, crash/system/video), plus copy candidates `port/src/preprocess/` (N64→PC asset conversion; `filemodel.c` is the D43 near-analogue) and `mixer.c`/`input.c`/`fs.c`. Port-layer files only; same family ≠ identical format — validate per field. Full audit: `docs/internals.md` §2.4. |
## Build ## Build
+14 -10
View File
@@ -3,14 +3,17 @@
Status: **plan only** — no code changes yet. Companion to `port/src/input.c` Status: **plan only** — no code changes yet. Companion to `port/src/input.c`
(current state: D118/D165/D166/D194/D214/D223/D238 lineage). (current state: D118/D165/D166/D194/D214/D223/D238 lineage).
## 1. The reference (vendored in-repo) ## 1. The reference (no longer vendored in the public repo)
The GEPD Edition Mouse Injector source is vendored at **`reference/mouse-injector/`** The GEPD Edition Mouse Injector source was vendored at `reference/mouse-injector/`
(see its README for provenance, version-skew warning, and a per-file guide). and **removed from the public repo on 2026-09-19** (GPLv2 code + a prebuilt
The file that matters is **`games/goldeneye.c`** (~380 lines, the whole GE binary inside an MIT project; never compiled here). See
aim model), plus `device.c` (raw mouse polling) and `maindll.h` (tickrate — `reference/mouse-injector/README.md` for provenance and how to re-vendor it
the units every per-tick constant assumes). Consult it directly; no locally if you need the original. The file that mattered was
re-extraction needed. **`games/goldeneye.c`** (~380 lines, the whole GE aim model), plus `device.c`
(raw mouse polling) and `maindll.h` (tickrate — the units every per-tick
constant assumes). The model is quoted inline below and in the D194 findings;
the ported result lives in `port/src/input.c`.
### What the Mouse Injector does (GE) ### What the Mouse Injector does (GE)
@@ -49,9 +52,10 @@ sensitivity/FOV coupling discipline. That's WIs 1–3 + 6 below.
Two references, two jobs (decided during #89/#90 triage): Two references, two jobs (decided during #89/#90 triage):
- **GEPD Mouse Injector** (`reference/mouse-injector/`) = *what the mouse does - **GEPD Mouse Injector** (was `reference/mouse-injector/`, removed from the
to the camera*. The only reference with GE-specific knowledge (camera public repo 2026-09-19 — see its README stub) = *what the mouse does to the
fields, crosshair limits, tank case, safety gates). Primary for WI-1. camera*. The only reference with GE-specific knowledge (camera fields,
crosshair limits, tank case, safety gates). Primary for WI-1.
- **PD PC port checkout** (standing reference, see AGENTS.md) = *how a PC game - **PD PC port checkout** (standing reference, see AGENTS.md) = *how a PC game
presents and captures input*: cursor-lock behavior, raw input handling, presents and captures input*: cursor-lock behavior, raw input handling,
sensitivity units/scaling, and the shipped in-game options/keybind UI. sensitivity units/scaling, and the shipped in-game options/keybind UI.
+7 -7
View File
@@ -17,17 +17,17 @@ D186,PARTIAL,"Video.FpsCap throttles the sim, not just presentation (M-39 diag,
D187,FIXED,"HUD ammo-type/weapon icon vanished at -O2 (M-46 root-cause, M-47 fix + verify).","FIXED (src/game/gunfire.c, #ifdef AVOID_UB); PR #19" D187,FIXED,"HUD ammo-type/weapon icon vanished at -O2 (M-46 root-cause, M-47 fix + verify).","FIXED (src/game/gunfire.c, #ifdef AVOID_UB); PR #19"
D188,FIXED,Linux -O2 boot crash:,"FIXED (src/libultrare/libc/xprintf.c, src/sprintf.c, #ifdef PORT); PR #22" D188,FIXED,Linux -O2 boot crash:,"FIXED (src/libultrare/libc/xprintf.c, src/sprintf.c, #ifdef PORT); PR #22"
D189,FIXED,Linux -fstack-protector aborts on the decomp's latent stack-buffer overruns (M-48) —,"FIXED (CMakeLists.txt, src/game/stan.c #ifdef PORT); PR #23" D189,FIXED,Linux -fstack-protector aborts on the decomp's latent stack-buffer overruns (M-48) —,"FIXED (CMakeLists.txt, src/game/stan.c #ifdef PORT); PR #23"
D190,?,"Linux -level_45 SIGSEGV at load in add_ptr_to_objective (objective.c:64) (M-48, open).","CLOSED — not a port bug; level 45 is MP-only and has no solo setup file in the ROM (root-caused M-105, reproduced on Windows)." D190,CLOSED,"Linux -level_45 SIGSEGV at load in add_ptr_to_objective (objective.c:64) (M-48, open).","CLOSED — not a port bug; level 45 is MP-only and has no solo setup file in the ROM (root-caused M-105, reproduced on Windows)."
D191,FIXED,Windows -O2 release-bundle crash:,FIXED + PLAYTEST-VERIFIED (M-79).… D191,FIXED,Windows -O2 release-bundle crash:,FIXED + PLAYTEST-VERIFIED (M-79).…
D193,FIXED,NPC AI locomotion is too slow —,FIXED + user-playtest-verified (M-81) —… D193,FIXED,NPC AI locomotion is too slow —,FIXED + user-playtest-verified (M-81) —…
D194,PARTIAL,Mouse input needs another tuning pass —,PARTIAL — M-120 human playtest… D194,PARTIAL,Mouse input needs another tuning pass —,PARTIAL — M-120 human playtest…
D195,FIXED,"Transparency / alpha surfaces broken on Control (M-49, user playtest) —","FIXED (port/fast3d/gfx_pc.cpp, gfx_sp_vertex) —…" D195,FIXED,"Transparency / alpha surfaces broken on Control (M-49, user playtest) —","FIXED (port/fast3d/gfx_pc.cpp, gfx_sp_vertex) —…"
D197,?,"Character face/head textures wrap around the head, seen on Silo (M-49, user playtest).",CLOSED — user playtest v0.2.0-pre D197,CLOSED,"Character face/head textures wrap around the head, seen on Silo (M-49, user playtest).",CLOSED — user playtest v0.2.0-pre
D198,FIXED,alAdpcmPull/_decodeChunk used K0_TO_PHYS (an unconditional & 0x1FFFFFFF mask) on 64-bit heap pointers (src/libultra/audio/load.c).,FIXED (src/libultra/audio/load.c) — D198,FIXED,alAdpcmPull/_decodeChunk used K0_TO_PHYS (an unconditional & 0x1FFFFFFF mask) on 64-bit heap pointers (src/libultra/audio/load.c).,FIXED (src/libultra/audio/load.c) —
D199,PARTIAL,Phase-3 software audio mixer:,"LANDED (port/src/mixer.c, port/include/mixer.h, include/PR/abi.h) —" D199,PARTIAL,Phase-3 software audio mixer:,"LANDED (port/src/mixer.c, port/include/mixer.h, include/PR/abi.h) —"
D200,FIXED,-level_09 segfault: reverb's ALDelay.input/output are u32 —,FIXED — 5-line cast in reverb.c (this session) D200,FIXED,-level_09 segfault: reverb's ALDelay.input/output are u32 —,FIXED — 5-line cast in reverb.c (this session)
D196,FIXED,"OS mouse cursor stays visible after closing the F10 options overlay in click-to-lock mode (M-49, user playtest).","FIXED (6e758f1d, merged to main) —…" D196,FIXED,"OS mouse cursor stays visible after closing the F10 options overlay in click-to-lock mode (M-49, user playtest).","FIXED (6e758f1d, merged to main) —…"
D192,?,Front-end mission/level-select grid pointer still can't reach the outer cells —,"CLOSED — the buggy mode 0 was removed entirely in the v0.2.0 prep pass (see D239); click-to-lock is now the only capture mode, so the unreachable-cells path no longer exists" D192,CLOSED,Front-end mission/level-select grid pointer still can't reach the outer cells —,"CLOSED — the buggy mode 0 was removed entirely in the v0.2.0 prep pass (see D239); click-to-lock is now the only capture mode, so the unreachable-cells path no longer exists"
D221,FIXED,SELECT FILE mouse hit-box offset —,"FIXED (M-91) — explicit {min,max} coord2d pairs under #ifdef PORT; human mouse-playtest confirmed." D221,FIXED,SELECT FILE mouse hit-box offset —,"FIXED (M-91) — explicit {min,max} coord2d pairs under #ifdef PORT; human mouse-playtest confirmed."
D222,FIXED,High Video.FovScale breaks culling —,"FIXED, awaiting visual verification (M-121)." D222,FIXED,High Video.FovScale breaks culling —,"FIXED, awaiting visual verification (M-121)."
D223,FIXED,QoL ask: mouse-wheel weapon cycling should be directional like a normal PC shooter —,"FIXED (M-105, port/src/input.c) —…" D223,FIXED,QoL ask: mouse-wheel weapon cycling should be directional like a normal PC shooter —,"FIXED (M-105, port/src/input.c) —…"
@@ -42,7 +42,7 @@ D234,FIXED,"Dam: guard towers along the dam structure invisible except the first
D244,OPEN,Self-hosted CI runner (corpyvt6agent01) link failure:,"OPEN, not yet fixed. Next…" D244,OPEN,Self-hosted CI runner (corpyvt6agent01) link failure:,"OPEN, not yet fixed. Next…"
D228,FIXED,AK47 white missing-texture patches after D217's texpool fix —,"FIXED (port/fast3d/gfx_pc.cpp, palette_to_rgba32) —" D228,FIXED,AK47 white missing-texture patches after D217's texpool fix —,"FIXED (port/fast3d/gfx_pc.cpp, palette_to_rgba32) —"
D204,FIXED,PC audio ran ~2 % below real time permanently (AI feedback loop's 3 ms setpoint vs PC jitter).,"FIXED (port/src/audio.c, port/src/libultra.c, port/include/audio.h) —" D204,FIXED,PC audio ran ~2 % below real time permanently (AI feedback loop's 3 ms setpoint vs PC jitter).,"FIXED (port/src/audio.c, port/src/libultra.c, port/include/audio.h) —"
D203,?,"Steam Deck (SteamOS, x86_64 Linux) v0.1.0 release bundle:",CLOSED — root cause + fix in D253. D203,CLOSED,"Steam Deck (SteamOS, x86_64 Linux) v0.1.0 release bundle:",CLOSED — root cause + fix in D253.
D201,FIXED,"src/libultra/audio/bnkf.c bank/instrument/sound/wavetable relocation offsets were s32, truncating the real 64-bit base pointer.",FIXED (src/libultra/audio/bnkf.c) — D201,FIXED,"src/libultra/audio/bnkf.c bank/instrument/sound/wavetable relocation offsets were s32, truncating the real 64-bit base pointer.",FIXED (src/libultra/audio/bnkf.c) —
D202,?,"Silenced PPK ""slap"" + broader real-time mixer corruption (M-52→M-67).",ROOT CAUSE ESTABLISHED (M-66); Disposition C implemented + measured (M-66b) — D202,?,"Silenced PPK ""slap"" + broader real-time mixer corruption (M-52→M-67).",ROOT CAUSE ESTABLISHED (M-66); Disposition C implemented + measured (M-66b) —
D206,FIXED,PC played every SFX one bank slot too high —,"FIXED (M-76, src/snd.c:1001, #ifdef PORT) —" D206,FIXED,PC played every SFX one bank slot too high —,"FIXED (M-76, src/snd.c:1001, #ifdef PORT) —"
@@ -50,7 +50,7 @@ D207,?,"Alarm klaxon starves combat SFX and doesn't recover after it stops (surf
D208,FIXED,Player weapon-fire sound goes permanently silent mid-firefight (all other SFX unaffected) —,FIXED + user playtest-verified (M-78d) — D208,FIXED,Player weapon-fire sound goes permanently silent mid-firefight (all other SFX unaffected) —,FIXED + user playtest-verified (M-78d) —
D209,FIXED,Every AI character in the game is locked to a *walk* animation regardless of the speed the ailist commands —,FIXED + user-playtest-verified (M-81). D209,FIXED,Every AI character in the game is locked to a *walk* animation regardless of the speed the ailist commands —,FIXED + user-playtest-verified (M-81).
D210,FIXED,chrToPatrol() leaves act_patrol.lastvisible60 uninitialised on PC —,"FIXED (chraction.c:3872, #ifdef PORT → self->act_patrol.lastvisible60 = -1;, N64 line under #else).…" D210,FIXED,chrToPatrol() leaves act_patrol.lastvisible60 uninitialised on PC —,"FIXED (chraction.c:3872, #ifdef PORT → self->act_patrol.lastvisible60 = -1;, N64 line under #else).…"
D205,RESOLVED,"PC plays wrong/extra SFX for gameplay events (gunfire slap layer, explosion→scream, armour pickup, melee→Klobb idx 106) —",CLOSED (M-78) — root cause was D206; all four symptoms resolved + user-confirmed by ear. D205,CLOSED,"PC plays wrong/extra SFX for gameplay events (gunfire slap layer, explosion→scream, armour pickup, melee→Klobb idx 106) —",CLOSED (M-78) — root cause was D206; all four symptoms resolved + user-confirmed by ear.
D152+,FIXED,D152 addendum (M-31):,"FIXED (src/snd.c, port/src/libultra.c, #ifdef PORT) —" D152+,FIXED,D152 addendum (M-31):,"FIXED (src/snd.c, port/src/libultra.c, #ifdef PORT) —"
D168,FIXED,GE_PCDUMP / F12 PPM captures were vertically flipped —,FIXED (port/fast3d/gfx_opengl.cpp); D114 / D116 reclassified as capture-orientation artifacts (below). D168,FIXED,GE_PCDUMP / F12 PPM captures were vertically flipped —,FIXED (port/fast3d/gfx_opengl.cpp); D114 / D116 reclassified as capture-orientation artifacts (below).
D169,FIXED,Front-end mouse pointer can't reach the outer cells of the mission/level-select grid —,"FIXED (M-33, port/src/input.c, port-only, no #ifdef PORT)." D169,FIXED,Front-end mouse pointer can't reach the outer cells of the mission/level-select grid —,"FIXED (M-33, port/src/input.c, port-only, no #ifdef PORT)."
@@ -135,7 +135,7 @@ D235,OPEN,Wrong textures load after dying/restarting a level —,OPEN — needs:
D236,OPEN,"Surface 1: 2D billboard trees render as a wall/sheet of tree texture instead of discrete camera-facing tree sprites (M-106, user QA report).","OPEN, sixteenth pass (2026-09-18) —" D236,OPEN,"Surface 1: 2D billboard trees render as a wall/sheet of tree texture instead of discrete camera-facing tree sprites (M-106, user QA report).","OPEN, sixteenth pass (2026-09-18) —"
D237,OPEN,"QoL ask (M-106, user QA):",OPEN — not designed; port-only D237,OPEN,"QoL ask (M-106, user QA):",OPEN — not designed; port-only
D238,OPEN,"QoL ask (M-106, user QA):",OPEN — not designed; port-only (port/src/input.c + config.c) D238,OPEN,"QoL ask (M-106, user QA):",OPEN — not designed; port-only (port/src/input.c + config.c)
D239,?,"QoL ask (M-106, user QA):",CLOSED — executed in the v0.2.0 prep pass (port-only)… D239,CLOSED,"QoL ask (M-106, user QA):",CLOSED — executed in the v0.2.0 prep pass (port-only)…
D240,OPEN,"Player gunshot SFX timing/cadence reportedly does not match the N64 original's rate (M-106, user QA report).","OPEN — not root-caused; static call-site tracing only, no runtime verification possible in this environment." D240,OPEN,"Player gunshot SFX timing/cadence reportedly does not match the N64 original's rate (M-106, user QA report).","OPEN — not root-caused; static call-site tracing only, no runtime verification possible in this environment."
D241,OPEN,Player gunshot SFX goes silent under some conditions —,"OPEN — not newly root-caused; high confidence this is D207 reproduced, not an independent bug." D241,OPEN,Player gunshot SFX goes silent under some conditions —,"OPEN — not newly root-caused; high confidence this is D207 reproduced, not an independent bug."
D242,?,Player-death sequence UX regression vs N64 original:,NOT A PORT-LOGIC BUG as far as static analysis can tell. D242,?,Player-death sequence UX regression vs N64 original:,NOT A PORT-LOGIC BUG as far as static analysis can tell.
@@ -194,7 +194,7 @@ D313,FIXED,Bullet impacts do not appear on some walls/surfaces —,"FIXED — sa
D314,OPEN,"F10 menu items flicker randomly/intermittently (reported on the main-menu context, user report, v0.3.0 playtest build, 2026-09-18).",OPEN — confirmed still present post-D316 fix (2026-09-18); user deprioritized chasing it further for now. D314,OPEN,"F10 menu items flicker randomly/intermittently (reported on the main-menu context, user report, v0.3.0 playtest build, 2026-09-18).",OPEN — confirmed still present post-D316 fix (2026-09-18); user deprioritized chasing it further for now.
D315,OPEN,Menu scaling differs between main menu and in-game —,"OPEN — disclosed as a known issue, deferred to v0.3.1 (bigger design question, not a mechanical fix)." D315,OPEN,Menu scaling differs between main menu and in-game —,"OPEN — disclosed as a known issue, deferred to v0.3.1 (bigger design question, not a mechanical fix)."
D316,FIXED,"Mouse-clicking some menu items glitches and lands on the item below instead (user report, v0.3.0 playtest build, 2026-09-18).",FIXED — root-caused to two compounding bugs (naive mouse->logical mapping ignoring the safe-area crop; asymmetric row hit-test band) in port/src/optionsoverlay.c + port/fast3d/gfx_pc.cpp. D316,FIXED,"Mouse-clicking some menu items glitches and lands on the item below instead (user report, v0.3.0 playtest build, 2026-09-18).",FIXED — root-caused to two compounding bugs (naive mouse->logical mapping ignoring the safe-area crop; asymmetric row hit-test band) in port/src/optionsoverlay.c + port/fast3d/gfx_pc.cpp.
D317,?,"Crash when toggling Game.AllUnlocked back and forth in-game (user report, v0.3.0 playtest build, 2026-09-18) —","CLOSED — symptom of D316 (confirmed instant window close, no WER report; the D316 hit-band bias let a click on ""All unlocked"" fall through to the adjacent ""Quit to desktop"" row)." D317,CLOSED,"Crash when toggling Game.AllUnlocked back and forth in-game (user report, v0.3.0 playtest build, 2026-09-18) —","CLOSED — symptom of D316 (confirmed instant window close, no WER report; the D316 hit-band bias let a click on ""All unlocked"" fall through to the adjacent ""Quit to desktop"" row)."
D318,RESOLVED,Facility (regular play path):,RESOLVED (2026-09-19): D318,RESOLVED,Facility (regular play path):,RESOLVED (2026-09-19):
D319,FIXED,"Frame cap slider was mostly a dead zone; replaced with a plain 30/60 toggle (user ask, 2026-09-18).",FIXED — new ROW_FPSCAP cycle (30/60 only) in port/src/optionsoverlay.c; default changed to 60 in port/src/video.c. D319,FIXED,"Frame cap slider was mostly a dead zone; replaced with a plain 30/60 toggle (user ask, 2026-09-18).",FIXED — new ROW_FPSCAP cycle (30/60 only) in port/src/optionsoverlay.c; default changed to 60 in port/src/video.c.
D320,OPEN,"D318-class sweep: aim-hold → _update AI lists in 8 levels carry the same as-authored softlock race (static analysis, 2026-09-20).","OPEN — static sweep complete (Facility ai_19, Control ai_9, Depot ai_12 flagged high/med-high; Bond-combat loops likely safe); no live confirmation beyond D318 itself; probe-verify path + generalized…" D320,OPEN,"D318-class sweep: aim-hold → _update AI lists in 8 levels carry the same as-authored softlock race (static analysis, 2026-09-20).","OPEN — static sweep complete (Facility ai_19, Control ai_9, Depot ai_12 flagged high/med-high; Bond-combat loops likely safe); no live confirmation beyond D318 itself; probe-verify path + generalized…"
1 # GENERATED by tools_pc/gen_findings_index.py -- do not hand-edit.
17 D187
18 D188
19 D189
20 D190
21 D191
22 D193
23 D194
24 D195
25 D197
26 D198
27 D199
28 D200
29 D196
30 D192
31 D221
32 D222
33 D223
42 D244
43 D228
44 D204
45 D203
46 D201
47 D202
48 D206
50 D208
51 D209
52 D210
53 D205
54 D152+
55 D168
56 D169
135 D236
136 D237
137 D238
138 D239
139 D240
140 D241
141 D242
194 D314
195 D315
196 D316
197 D317
198 D318
199 D319
200 D320
+17 -3
View File
@@ -11707,7 +11707,7 @@ Returns "cheat not unlocked" — the same safe default other cheat-state paths a
**Status:** FIXED locally on `release/v0.3.0` (not yet pushed) — build-verified, crash-free smoke test; live confirmation against the actual #87 repro still owed. **Status:** FIXED locally on `release/v0.3.0` (not yet pushed) — build-verified, crash-free smoke test; live confirmation against the actual #87 repro still owed.
**M-183/M-185 (2026-09-17, this session):** Added playspeed and endframe clamp workarounds for D243's Bond position/animation issue. M-183 clamps playspeed > 10.0 to 1.0 during scripted camera modes; M-185 clamps corrupted endframe values (< 0.0 or > 1000.0) to 100.0. Both are + env-gated on GE_D243M. The clamp fixes prevent rapid animation advancement (~97 frames/tick) but Bond's animation still "repeats" — he can't complete his animation during the Dam abseil cutscene. ~~Root cause (struct layout corruption from 32→64-bit pointer widening, D100/D140 family) not yet addressed.~~ **M-183/M-185 (2026-09-17, this session):** Added playspeed and endframe clamp workarounds for D243's Bond position/animation issue. M-183 clamps playspeed > 10.0 to 1.0 during scripted camera modes; M-185 clamps corrupted endframe values (< 0.0 or > 1000.0) to 100.0. Both were originally env-gated on GE_D243M — a gate M-187 found to be wrong (the clamps never fired for real players); they are now gated on `gameScriptedCameraActive()` alone and active by default. See M-192 for the v0.3.0 release-review sign-off on their retention. The clamp fixes prevent rapid animation advancement (~97 frames/tick) but Bond's animation still "repeats" — he can't complete his animation during the Dam abseil cutscene. ~~Root cause (struct layout corruption from 32→64-bit pointer widening, D100/D140 family) not yet addressed.~~
**M-186 (2026-09-17, later recovery session) — the M-183/M-185 diagnosis above is WRONG; correcting the record.** A follow-up agent acted on "struct layout corruption from pointer widening" and converted `Model`'s 7 pointer fields to u32 slots + accessor macros, rewriting ~200 call sites with blind `sed` across 12 files — this broke the build (macro name collisions with unrelated structs' same-named fields, malformed chained-access substitutions) and was **reverted this session** (changes stashed, not committed: `git stash` "D243 broken sed attempt (superseded)"). The diagnosis itself doesn't hold up: a `Model*` accessed normally is always self-consistent post-compilation; this codebase's actual pointer-widening bug class only bites when something *puns/overlays* a Model onto raw hardcoded-offset bytes (§A, `porting-notes.md`), and all three known instances of that for models (D100 Bond's own inline model, D102 weapon model, D140 watch model) are already fixed with real inline storage. No unfixed punning gap exists for Bond's world model. **The real, already-established lead is above this entry, in M-169 through M-178** — the 3rd `chrlvPerformAnimationForActor` scripted restart (`chraction.c:605`) triggers the rapid `animframe` advancement; M-178's own stated next step (diff that call's caller-side state writes, `chraction.c:615-627`, against a normal `modelTickAnim` loop-wrap) was never carried out and is the correct place to resume. See `docs/HANDOFF.md` for the fuller writeup, including a new unconfirmed candidate (`modelSetAnimation`/`modelSetAnimation2` never reset `playspeed`/`unkb0`/`unkb4`/`unkac`/`animrate`, only `modelSetAnimPlaySpeed` does) that needs a live `GE_D243M` capture to check, and a reminder not to lose D243 CONSOLIDATED NEXT STEPS item 5's model-pointer-reuse caveat as an alternative explanation for the "playspeed already corrupted before `modelSetAnimPlaySpeed` was even called" observation. **M-186 (2026-09-17, later recovery session) — the M-183/M-185 diagnosis above is WRONG; correcting the record.** A follow-up agent acted on "struct layout corruption from pointer widening" and converted `Model`'s 7 pointer fields to u32 slots + accessor macros, rewriting ~200 call sites with blind `sed` across 12 files — this broke the build (macro name collisions with unrelated structs' same-named fields, malformed chained-access substitutions) and was **reverted this session** (changes stashed, not committed: `git stash` "D243 broken sed attempt (superseded)"). The diagnosis itself doesn't hold up: a `Model*` accessed normally is always self-consistent post-compilation; this codebase's actual pointer-widening bug class only bites when something *puns/overlays* a Model onto raw hardcoded-offset bytes (§A, `porting-notes.md`), and all three known instances of that for models (D100 Bond's own inline model, D102 weapon model, D140 watch model) are already fixed with real inline storage. No unfixed punning gap exists for Bond's world model. **The real, already-established lead is above this entry, in M-169 through M-178** — the 3rd `chrlvPerformAnimationForActor` scripted restart (`chraction.c:605`) triggers the rapid `animframe` advancement; M-178's own stated next step (diff that call's caller-side state writes, `chraction.c:615-627`, against a normal `modelTickAnim` loop-wrap) was never carried out and is the correct place to resume. See `docs/HANDOFF.md` for the fuller writeup, including a new unconfirmed candidate (`modelSetAnimation`/`modelSetAnimation2` never reset `playspeed`/`unkb0`/`unkb4`/`unkac`/`animrate`, only `modelSetAnimPlaySpeed` does) that needs a live `GE_D243M` capture to check, and a reminder not to lose D243 CONSOLIDATED NEXT STEPS item 5's model-pointer-reuse caveat as an alternative explanation for the "playspeed already corrupted before `modelSetAnimPlaySpeed` was even called" observation.
@@ -11751,6 +11751,18 @@ Returns "cheat not unlocked" — the same safe default other cheat-state paths a
Build clean (`./build-pc.sh ntsc-final`), `tools_pc/verify.sh dam` PASS. **User confirmed both fixes live, full Dam intro-flyover + abseil-jump + abseil-descent playthrough: "ok yeah looks good."** Build clean (`./build-pc.sh ntsc-final`), `tools_pc/verify.sh dam` PASS. **User confirmed both fixes live, full Dam intro-flyover + abseil-jump + abseil-descent playthrough: "ok yeah looks good."**
### M-192 (2026-09-19): v0.3.0 release review — sign-offs, watchdog re-arm, repo hygiene, post-release cleanup list
Adversarial pre-ship review of the whole v0.3.0 window (147 commits since v0.2.2). Build verified clean (`./build-pc.sh ntsc-final`, 244/244 + link); `gen_findings_index.py --check` and `gen_env_probes.py --check` both pass. Outcomes, per user decisions in-thread:
1. **M-183/M-185 clamps (this section): RULE-2-SIGNOFF granted for RETENTION.** They are ungated behavior-modifying guards in `src/game/model.c` outside the ABI/layout exception; with M-189's root cause fixed and user-verified they no longer fire in practice, but removing them a day before ship would drop defense-in-depth across ALL cutscenes (verification so far covers Dam only). User approved retention as the stability-maximizing option. In-code comments updated (incl. fixing the stale "Threshold: 50.0" — code uses 10.0f). **Post-release: re-verify all scripted-camera cutscenes with the clamps compiled out; if clean, delete both blocks (reverts to pure decomp).**
2. **D311 heal clamps (`model.c`): RULE-2-SIGNOFF granted for RETENTION** — same decision, classified as defensive guards against non-finite state in the accepted D156 class (fire only on poison values; snap to valid frames; never touch legitimate animation). See the D311 entry.
3. **D318 watchdog re-arm (fixed this pass).** `port/src/d318watchdog.c` was one-shot per PROCESS: `s_fired` never reset, so a Facility replay later in the same session (AllUnlocked) hitting the same race would softlock with no recovery — the exact scenario the feature exists to prevent. Now one-shot per OCCURRENCE: after firing, the watchdog re-arms once the signature has been absent for `D318_REARM_TICKS` (600 ≈ 10 s) consecutive ticks; logs a `D318W: ... re-armed` line.
4. **GPL reference source removed from the public repo.** `reference/mouse-injector/` (GEPD-Edition Mouse Injector, GPLv2, incl. a prebuilt `discord-rpc.lib`) was committed inside the v0.3.0 window of an MIT project and would have shipped in the tag's auto-generated source tarball. Removed; a provenance stub README remains (`reference/mouse-injector/README.md`), the path is gitignored for local re-vendoring, and AGENTS.md / `docs/dev/GEPD-INPUT-PLAN.md` / `optionsoverlay.c` references were updated. The ported model lives in `port/src/input.c` (D194 lineage).
5. **`scratch/` untracked + gitignored.** 19 session logs / investigation scratch files (incl. a 1396-line regression log and probe `.c` sources) had been committed; removed from the index, `/scratch/` added to `.gitignore`. Local copies untouched.
6. **D310 perf gauge (no change needed).** v2's up-front `chraiGetAIListID()` in `chraiGoToLabel` adds ≤ (level-local + ~20 global) pointer comparisons per label jump, on a path that previously ran only in the rare EndList-not-found branch. Worst case for a heavy level (Train/Archives, ~50 active guards × 1–2 goto-family records/tick): ~1000 calls/tick × ~40 comparisons ≈ 40 µs/tick < 0.3% of a 16.7 ms frame — two orders of magnitude below D250's per-triangle `getenv` anti-pattern. Re-measure only if an AI-heavy level regresses.
7. **Post-release cleanup list (deferred by user):** (a) remove the TEMP diagnostic probes marked "remove once Dxxx concludes" whose investigations have ended (D236 passes 10/12/14/16 in `gfx_pc.cpp` + `GE_D236RAW` in `bg.c`, D288, D157, D252, D245V); (b) cache the few remaining per-call `getenv()`s on tick paths (bondview2 D243CAM ×3, chrai `AI_PLAYANIMATION` GE_D243M, sky.c water GE_D245_FIXEDSHIFT) per the D250 discipline; (c) delete M-183/M-185 if cutscene re-verification passes (item 1); (d) D317's latent heap-corruption class (39 dev-run crashes, pre-final-fix) stays on the radar — see its entry.
## D302 — Render FPS regression to ~40-45fps on release/v0.3.0 (user QA on the local v0.3.0 pre-release build, 2026-09-18). ## D302 — Render FPS regression to ~40-45fps on release/v0.3.0 (user QA on the local v0.3.0 pre-release build, 2026-09-18).
**User reported drops to 40-45fps on a self-described high-end PC on a local v0.3.0 pre-release build**, after the port had previously held a rock-steady 60-61fps end-to-end (D250, fully resolved). Same symptom class and roughly the same fps range as D250's original regression. **User reported drops to 40-45fps on a self-described high-end PC on a local v0.3.0 pre-release build**, after the port had previously held a rock-steady 60-61fps end-to-end (D250, fully resolved). Same symptom class and roughly the same fps range as D250's original regression.
@@ -11950,6 +11962,8 @@ This confirms the M-160/M-164/M-165 hypothesis (`## D173`'s own consolidated-nex
**Cross-refs:** D309 (this fix neutralizes its spin mechanism — the teardown-ordering open question in D309's "why PC and not N64" remains, but reaching that state is now harmless); GE_D309 probes (`chrai.c` `ai()`/`chraiGoToLabel`, `chraction.c` `chrGoToBond`) remain as diagnostic tools. **Cross-refs:** D309 (this fix neutralizes its spin mechanism — the teardown-ordering open question in D309's "why PC and not N64" remains, but reaching that state is now harmless); GE_D309 probes (`chrai.c` `ai()`/`chraiGoToLabel`, `chraction.c` `chrGoToBond`) remain as diagnostic tools.
**Perf gauge (2026-09-19, release review — M-192 item 6):** v2's up-front `chraiGetAIListID()` call in `chraiGoToLabel` (added so the sizer knows global-vs-local) runs on EVERY label jump; originally that lookup ran only in the rare EndList-not-found branch. Cost per call: ≤ (level-local lists + ~20-entry `g_GlobalAILists`) pointer comparisons ≈ tens of ns. Worst case for a heavy level (Train/Archives, ~50 active guards each executing 1–2 goto-family records per tick): ~1000 calls/tick × ~40 comparisons ≈ 40 µs/tick — under 0.3% of a 16.7 ms frame, and two orders of magnitude below the D250 `getenv` anti-pattern (which was per-TRIANGLE, tens of thousands of calls per frame). **No change warranted; re-measure only if an AI-heavy level shows a regression.**
## D311 — Complete freeze in `modelSetAnimFrame2WithChrStuff` root-motion loop: D156 guard hole — poisoned `framea` (`model->animframe1`) passes through the frameb-only clamp and saturates to a ~3.1e9-iteration spin (Caverns, live GDB diagnosis, 2026-09-18). ## D311 — Complete freeze in `modelSetAnimFrame2WithChrStuff` root-motion loop: D156 guard hole — poisoned `framea` (`model->animframe1`) passes through the frameb-only clamp and saturates to a ~3.1e9-iteration spin (Caverns, live GDB diagnosis, 2026-09-18).
**Reported:** user playtest of the D310 v2 build in Caverns — "it's frozen" shortly after launch (watchdog: no frame rendered for 8014 ms at frames=8424; ~2.3 min into the session). **Reported:** user playtest of the D310 v2 build in Caverns — "it's frozen" shortly after launch (watchdog: no frame rendered for 8014 ms at frames=8424; ~2.3 min into the session).
@@ -11967,7 +11981,7 @@ This confirms the M-160/M-164/M-165 hypothesis (`## D173`'s own consolidated-nex
**Open question (deeper root cause, NOT fixed):** what wrote `-1.75e18` into `oldspeed` / poisoned `animframe1` in the first place? `oldspeed = model->speed` at transition start (`model.c:2975`) means `speed` was already garbage upstream; `timespeed = 0` and `unkb0 = 0` at the guarded tick are suspicious division denominators (D156's original note flagged `/ unkb0` and `/ timespeed` as guarded `> 0` but not against tiny values). Also, the model's persistent root-motion header (`header->unk34/unk24`) is poisoned to ~1e30–1e32 in this instance, so **Bond's rendered model may be displaced even after the freeze is prevented** — a level reload clears it. Needs its own investigation (dump speed-field write sites during the triggering transition) before any further fix. **Open question (deeper root cause, NOT fixed):** what wrote `-1.75e18` into `oldspeed` / poisoned `animframe1` in the first place? `oldspeed = model->speed` at transition start (`model.c:2975`) means `speed` was already garbage upstream; `timespeed = 0` and `unkb0 = 0` at the guarded tick are suspicious division denominators (D156's original note flagged `/ unkb0` and `/ timespeed` as guarded `> 0` but not against tiny values). Also, the model's persistent root-motion header (`header->unk34/unk24`) is poisoned to ~1e30–1e32 in this instance, so **Bond's rendered model may be displaced even after the freeze is prevented** — a level reload clears it. Needs its own investigation (dump speed-field write sites during the triggering transition) before any further fix.
**Status:** GUARDED (freeze class neutralized; upstream poison source OPEN). Disclosed to user in-thread as a D156-guard extension following the already-accepted D156 precedent in this same file; if the project wants formal rule-2 sign-off for `src/game` edits, this is the entry to reference — revert is two small blocks. Cross-refs: D156 (original guard + Facility outro hang), D309/D310 (ruled out for this freeze — no AI involvement). **Status:** GUARDED (freeze class neutralized; upstream poison source OPEN). **RULE-2-SIGNOFF (2026-09-19, release review — M-192 item 2):** user approved retention as the stability-maximizing option; classified as a defensive guard against non-finite state in the same class as the accepted D156 guards — it fires only on poison values that indicate an already-broken state and snaps to a valid frame rather than altering any legitimate animation. Previously disclosed in-thread as a D156-guard extension following the already-accepted D156 precedent in this same file; revert is still two small blocks. Cross-refs: D156 (original guard + Facility outro hang), D309/D310 (ruled out for this freeze — no AI involvement).
## D312 — Throwable items (mines, grenades, etc.) can clip through walls in certain spots (user report, v0.3.0 pre-release playtest, 2026-09-18) — FIXED: `bgBuildRoomVtxBounds` mis-reads the G_VTX vertex count on PC (Gfx_le `dma.par` bit-layout shift), collapsing whole batches of wall geometry out of the collision query (diagnosed + fixed, 2026-09-18). ## D312 — Throwable items (mines, grenades, etc.) can clip through walls in certain spots (user report, v0.3.0 pre-release playtest, 2026-09-18) — FIXED: `bgBuildRoomVtxBounds` mis-reads the G_VTX vertex count on PC (Gfx_le `dma.par` bit-layout shift), collapsing whole batches of wall geometry out of the collision query (diagnosed + fixed, 2026-09-18).
@@ -12097,7 +12111,7 @@ Ourumov = chr 78 on list 0x0417 (ai_22). Key offsets: off=38 pre-aim at Trevelya
### Fix (port-side, `port/src/d318watchdog.c` — same pattern as D202 M-66b) ### Fix (port-side, `port/src/d318watchdog.c` — same pattern as D202 M-66b)
Per-tick check (hooked at the `g_GlobalTimer += g_ClockTimer` site in lv.c). Signature, all held for 600 consecutive ticks (10 s; the escape path resolves in < 2 s): chr 78 on list 0x0417 with offset in [321, 333), `actiontype == ACT_ATTACK`, `act_attack.entityid == 67` (targeting Trevelyan — legitimate combat at this offset targets Bond, ent=1), and chr 67 alive. On confirm: **re-initialize c78's attack via `sub_GAME_7F025560(c78, attacktype, entityid)`** — the same entry point the game itself uses for a fresh attack (chrlvTickAttack type_of_motion==2, chraction.c:7401). That runs `chrlvInitActAttack` → random variant + `modelSetAnimation(start_frame)`, breaking the pin; c78 then live-fires Trevelyan exactly like the natural escape path. One-shot; logs `D318W:` lines for playtest audit; opt-out `GE_D318W=0`. Per-tick check (hooked at the `g_GlobalTimer += g_ClockTimer` site in lv.c). Signature, all held for 600 consecutive ticks (10 s; the escape path resolves in < 2 s): chr 78 on list 0x0417 with offset in [321, 333), `actiontype == ACT_ATTACK`, `act_attack.entityid == 67` (targeting Trevelyan — legitimate combat at this offset targets Bond, ent=1), and chr 67 alive. On confirm: **re-initialize c78's attack via `sub_GAME_7F025560(c78, attacktype, entityid)`** — the same entry point the game itself uses for a fresh attack (chrlvTickAttack type_of_motion==2, chraction.c:7401). That runs `chrlvInitActAttack` → random variant + `modelSetAnimation(start_frame)`, breaking the pin; c78 then live-fires Trevelyan exactly like the natural escape path. One-shot per OCCURRENCE: after firing, the watchdog re-arms once the signature has been absent for 600 consecutive ticks (~10 s), so a later replay of Facility in the same session (AllUnlocked) is still covered — added 2026-09-19 during the v0.3.0 release review (M-192 item 3; previously one-shot per process, which would have left a replayed Facility unprotected). Logs `D318W:` lines for playtest audit; opt-out `GE_D318W=0`.
**Why not just kill Trevelyan:** first attempt applied the scripted headshot's own damage call (`handles_shot_actors(c67, 0x08, &zero, 0x06, FALSE)` — ai_22 off=333). c67 died, but a pinned attack has **no completion event tied to target death** — c78 stayed in ACT_ATTACK and the stop check still never passed (probe-verified: act=8 in 100% of samples post-kill vs 32/264 ACT_STAND samples in natural-escape runs). The attack state itself must be re-seeded. **Why not just kill Trevelyan:** first attempt applied the scripted headshot's own damage call (`handles_shot_actors(c67, 0x08, &zero, 0x06, FALSE)` — ai_22 off=333). c67 died, but a pinned attack has **no completion event tied to target death** — c78 stayed in ACT_ATTACK and the stop check still never passed (probe-verified: act=8 in 100% of samples post-kill vs 32/264 ACT_STAND samples in natural-escape runs). The attack state itself must be re-seeded.
+5
View File
@@ -54,6 +54,11 @@ Python — but an unpinned dependency means a future PyInstaller release
could change what ships without a corresponding diff in this repository. could change what ships without a corresponding diff in this repository.
Pinning it is a tracked follow-up. Pinning it is a tracked follow-up.
One development-only backdoor exists in source builds: the `GE_DEBUG_UNLOCKALL`
environment variable (`src/game/file2.c`) pre-unlocks all cheat options at boot.
It is off unless explicitly set, changes no shipped behavior, and is documented
here so the env-var surface stays fully accounted for.
## Fidelity to the original N64 game ## Fidelity to the original N64 game
The port's non-negotiable rule is that decompiled game logic is never The port's non-negotiable rule is that decompiled game logic is never
+44 -21
View File
@@ -68,7 +68,11 @@
* In every non-deadlocked state the watchdog is inert: the escape path * In every non-deadlocked state the watchdog is inert: the escape path
* kills Trevelyan within ~25-100 ticks (60x under the threshold) and * kills Trevelyan within ~25-100 ticks (60x under the threshold) and
* legitimate combat never targets chr 67 from this loop. One-shot per * legitimate combat never targets chr 67 from this loop. One-shot per
* process; logs its detection and intervention for playtest audit. * OCCURRENCE: after firing, it re-arms once the signature has been absent
* for D318_REARM_TICKS consecutive ticks (the deadlock is gone -- recovered
* or the player moved on), so a later replay of Facility in the same
* session (AllUnlocked) is still covered. Logs its detection and
* intervention for playtest audit.
* *
* Opt out (research only): GE_D318W=0 * Opt out (research only): GE_D318W=0
*/ */
@@ -100,6 +104,7 @@ extern void sub_GAME_7F025560(ChrRecord *self, s32 attack_type, s32 arg2);
#define D318_OURUMOV_CHR 78 #define D318_OURUMOV_CHR 78
#define D318_TREVELYAN_CHR 67 #define D318_TREVELYAN_CHR 67
#define D318_DEADLOCK_TICKS 600 /* 10 s at 60 Hz; escape takes < 2 s */ #define D318_DEADLOCK_TICKS 600 /* 10 s at 60 Hz; escape takes < 2 s */
#define D318_REARM_TICKS 600 /* signature-absent ticks before re-arm */
static ChrRecord *d318wFindChr(s16 chrnum) static ChrRecord *d318wFindChr(s16 chrnum)
{ {
@@ -124,12 +129,14 @@ static ChrRecord *d318wFindChr(s16 chrnum)
void d318WatchdogTick(void) void d318WatchdogTick(void)
{ {
static int s_enabled = -1; /* -1 uncached, 0 off (GE_D318W=0), 1 on */ static int s_enabled = -1; /* -1 uncached, 0 off (GE_D318W=0), 1 on */
static s32 s_run = 0; /* consecutive ticks the signature has held */ static s32 s_run = 0; /* consecutive ticks the signature has held */
static bool s_fired = FALSE; static s32 s_absent = 0; /* consecutive ticks signature absent */
static bool s_fired = FALSE;
ChrRecord *c78; ChrRecord *c78;
ChrRecord *c67; ChrRecord *c67;
bool g = FALSE; bool g = FALSE;
bool sig;
if (s_enabled < 0) if (s_enabled < 0)
{ {
@@ -137,7 +144,7 @@ void d318WatchdogTick(void)
s_enabled = (e && e[0] == '0') ? 0 : 1; s_enabled = (e && e[0] == '0') ? 0 : 1;
} }
if (!s_enabled || s_fired) if (!s_enabled)
{ {
return; return;
} }
@@ -145,33 +152,49 @@ void d318WatchdogTick(void)
c78 = d318wFindChr(D318_OURUMOV_CHR); c78 = d318wFindChr(D318_OURUMOV_CHR);
c67 = d318wFindChr(D318_TREVELYAN_CHR); c67 = d318wFindChr(D318_TREVELYAN_CHR);
if (c78 && c78->ailist sig = (c78 && c78->ailist
&& chraiGetAIListID(c78->ailist, &g) == D318_LIST_AI22 && chraiGetAIListID(c78->ailist, &g) == D318_LIST_AI22
&& c78->aioffset >= D318_OFF_LOOP_MIN && c78->aioffset < D318_OFF_LOOP_MAX && c78->aioffset >= D318_OFF_LOOP_MIN && c78->aioffset < D318_OFF_LOOP_MAX
&& c78->actiontype == ACT_ATTACK && c78->actiontype == ACT_ATTACK
&& (s32)c78->act_attack.entityid == D318_TREVELYAN_CHR && (s32)c78->act_attack.entityid == D318_TREVELYAN_CHR
&& c67 && c67->prop && !chrIsDead(c67)) && c67 && c67->prop && !chrIsDead(c67));
if (sig)
{ {
if (s_run == 1) s_absent = 0;
if (!s_fired)
{ {
osSyncPrintf("D318W: t=%d deadlock signature detected (c78 ai_22 off=%d " if (s_run == 1)
"ACT_ATTACK ent=67, c67 alive) -- starting %d-tick confirmation window\n", {
(int)g_GlobalTimer, (int)c78->aioffset, D318_DEADLOCK_TICKS); osSyncPrintf("D318W: t=%d deadlock signature detected (c78 ai_22 off=%d "
} "ACT_ATTACK ent=67, c67 alive) -- starting %d-tick confirmation window\n",
s_run++; (int)g_GlobalTimer, (int)c78->aioffset, D318_DEADLOCK_TICKS);
if (s_run >= D318_DEADLOCK_TICKS) }
{ s_run++;
osSyncPrintf("D318W: t=%d D318 execution deadlock confirmed -- re-initializing " if (s_run >= D318_DEADLOCK_TICKS)
"c78's attack (sub_GAME_7F025560 atk=0x%x ent=%d) to break the anim pin\n", {
(int)g_GlobalTimer, (unsigned)c78->act_attack.attacktype, osSyncPrintf("D318W: t=%d D318 execution deadlock confirmed -- re-initializing "
(int)c78->act_attack.entityid); "c78's attack (sub_GAME_7F025560 atk=0x%x ent=%d) to break the anim pin\n",
sub_GAME_7F025560(c78, (s32)c78->act_attack.attacktype, (s32)c78->act_attack.entityid); (int)g_GlobalTimer, (unsigned)c78->act_attack.attacktype,
s_fired = TRUE; (int)c78->act_attack.entityid);
sub_GAME_7F025560(c78, (s32)c78->act_attack.attacktype, (s32)c78->act_attack.entityid);
s_fired = TRUE;
}
} }
} }
else else
{ {
s_run = 0; s_run = 0;
/* One-shot per occurrence: once the deadlock signature has been
* clear for a while after a fire, re-arm so a later replay of
* Facility in the same process (AllUnlocked) is still covered. */
if (s_fired && ++s_absent >= D318_REARM_TICKS)
{
s_fired = FALSE;
s_absent = 0;
osSyncPrintf("D318W: t=%d signature clear for %d ticks -- watchdog re-armed\n",
(int)g_GlobalTimer, D318_REARM_TICKS);
}
} }
} }
+3 -1
View File
@@ -149,7 +149,9 @@ static struct Row rows[] = {
* over the same risk are pulled from the menu entirely; only the single * over the same risk are pulled from the menu entirely; only the single
* master `Input.MouseSensitivity` row below remains player-facing, exactly * master `Input.MouseSensitivity` row below remains player-facing, exactly
* mirroring the reference GEPD/PD injector model this input was ported * mirroring the reference GEPD/PD injector model this input was ported
* from (`reference/mouse-injector/games/goldeneye.c`) -- ONE user-facing * from (GEPD-Edition Mouse Injector's goldeneye.c -- source no longer
* vendored in the public repo, see reference/mouse-injector/README.md) --
* ONE user-facing
* sensitivity value, with the two per-mode constants staying fixed at * sensitivity value, with the two per-mode constants staying fixed at
* their calibrated (38/50) defaults, never independently player-tunable. * their calibrated (38/50) defaults, never independently player-tunable.
* Config vars + SensLink logic stay in `input.c`/`rowSet()` untouched * Config vars + SensLink logic stay in `input.c`/`rowSet()` untouched
-280
View File
@@ -1,280 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
+22 -34
View File
@@ -1,40 +1,28 @@
# GEPD Edition — Mouse Injector (vendored reference source) # mouse-injector (removed from public repo)
Vendored **read-only reference** for the PC port's input layer. NOT compiled The GEPD-Edition Mouse Injector source (GPLv2, ~1.5 MB including a prebuilt
by our build; never modify it — treat it like `rsp/graphics/gmain.s` `discord-rpc.lib`) was vendored here as a read-only reference for the PC
(ground truth we consult, not code we ship). port's mouse-aim model, and **removed from the public repo on 2026-09-19**
during the v0.3.0 release review: it is GPL-licensed code (plus a binary)
inside an MIT-licensed project, and it is not compiled or linked by anything
in this tree — it was consulted by developers only.
## Provenance ## Provenance (if you need to re-vendor it locally)
Extracted from `source.tar.xz` inside the GEPD Edition 1964 bundle - Project: "GEPD-Edition Mouse Injector" (GoldenEye 007 / Perfect Dark N64
(`C:\Users\james\Games\Emulators\Nintendo 64\1964_GEPD_Edition\1964\`). mouse-aim injection for emulators), GPLv2.
The Mouse Injector is a Project64/1964 input plugin that emulates the N64 - The file that mattered was `games/goldeneye.c` (~380 lines — the whole GE
controller from keyboard/mouse while injecting mouse-aim state directly into aim/hipfire/menu model), plus `device.c` (raw mouse polling) and
GoldenEye 007 / Perfect Dark game memory. License: **GPLv2** (see `maindll.h` (tickrate units).
`LICENSE.TXT`; `manymouse/` carries its own license).
**Version skew:** the tarball is a mix of eras — `device.c`, `ui/` are from ## What replaced it in this repo
the 2014 v1.5d line; `games/goldeneye.c`, `maindll.h`, `maindll.c` are dated
2021–22; the bundle's binary is a 2023 build with a few later additions. The
aim *model* in `games/goldeneye.c` is stable across those versions and is the
one we already mirrored (finding D194). Consult it for the model and
constants, not as an exact match to any single release.
## Key files - The ported, calibrated result lives in `port/src/input.c` (the D194
lineage; see `docs/dev/GEPD-INPUT-PLAN.md` for the design record, which
quotes the model inline).
- Historical findings that cite `reference/mouse-injector/...` paths
(`docs/dev/findings.md`, D194/D214/etc.) remain accurate as written; the
cited file content is preserved in those write-ups.
| File | What to look at | If you want the original source again for reference work, clone it locally
|---|---| into `reference/mouse-injector/` (it is gitignored now) — do not commit it.
| `games/goldeneye.c` | **The whole GE input/aim model.** `GE_Inject()` = hipfire direct camera write + tank + menu cursor; `GE_AimMode()` = crosshair-position aim (±5.159° limit, 72% edge threshold, 475/s scroll — the D194 source); `GE_Crouch()` = crouch-toggle state machine; `GE_Controller()` = button mapping (wheel→weapon macro, aim=B in menus); `GE_InjectHacks()` = ROM patches we do NOT port (reload key, FOV override) but which document intended behavior. |
| `games/perfectdark.c` | PD analogue of the same model (radial menu, hoverbike, camspy). |
| `device.c` / `manymouse/` | Raw-driver mouse polling + cursor lock (`SetCursorPos` cadence), wheel cooldown handling, multi-device mapping. |
| `maindll.h` | `TICKRATE`/`TIMESTEP` (2 ms overclocked / 4 ms stock) — the units every per-tick constant in `goldeneye.c` assumes. |
| `global.h` | Settings enum (sensitivity range 1..80, acceleration, crosshair-movement %, invert pitch, crouch toggle, aim mode). |
| `vkey.h` | Default key layout (WASD=C-buttons, Q=A, E=B, R=reload, wheel=weapon cycle). |
## Cross-references in our tree
- `docs/dev/GEPD-INPUT-PLAN.md` — plan for the remaining GEPD inheritances
(issues #89/#90).
- `port/src/input.c` — D194 (`aimGepdCompute`) is our mirror of
`GE_AimMode()`; D223 wheel cycling mirrors `GE_Controller()`'s weapon macro.
- `docs/dev/findings.md` §D194/D238 — aim-mode history and tuning.
-320
View File
@@ -1,320 +0,0 @@
//==========================================================================
// Mouse Injector Plugin
//==========================================================================
// Copyright (C) 2016-2021 Carnivorous
// All rights reserved.
//
// Mouse Injector is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, visit http://www.gnu.org/licenses/gpl-2.0.html
//==========================================================================
#include <stdlib.h>
#include <windows.h>
#include "global.h"
#include "device.h"
#include "maindll.h"
#include "./manymouse/manymouse.h"
#include "./games/game.h"
#define VK_LBUTTON 0x01 // IDs from vkey.h
#define VK_RBUTTON 0x02
#define VK_MBUTTON 0x04
#define VK_XBUTTON1 0x05
#define VK_XBUTTON2 0x06
#define VK_WHEELUP 0x0A
#define VK_WHEELDOWN 0x0B
#define VK_WHEELLEFT 0x0E
#define VK_WHEELRIGHT 0x0F
static int alreadyexec = 0; // has init already exec?
static int connected = 0; // number of devices connected
static POINT lockpos = {0}; // coords for mouse lock position
int windowactive = 1; // is emulator window active?
int DEV_Init(void);
void DEV_Quit(void);
DWORD WINAPI DEV_InjectThread();
int DEV_ReturnKey(void);
int DEV_ReturnDeviceID(const int devicetype);
const char *DEV_Name(const int id);
int DEV_Type(const int id);
int DEV_TypeIndex(const int id);
int DEV_TypeID(const int id, const int devicetype);
//==========================================================================
// Purpose: First called upon device launch, returns total connected ms/kb
// Changes Globals: alreadyexec, connected
//==========================================================================
int DEV_Init(void)
{
if(!alreadyexec)
{
alreadyexec = 1;
connected = ManyMouse_Init();
int activemice = 0, activekeyboards = 0;
for(int index = 0; index < connected; index++)
{
if(DEV_Type(index) == MOUSETYPE)
activemice = 1;
else
activekeyboards = 1;
}
if(!activemice || !activekeyboards) // fail if mouse or keyboard not detected (mouse and keyboard are required for this plugin)
connected = 0;
}
if(connected >= 2) // if at least one mouse and keyboard are detected
return connected;
return 0;
}
//==========================================================================
// Purpose: Safely close ManyMouse
// Changes Globals: alreadyexec, connected
//==========================================================================
void DEV_Quit(void)
{
ManyMouse_Quit();
alreadyexec = 0;
connected = 0;
}
//==========================================================================
// Purpose: Polls ManyMouse for input and injects into game
// Changes Globals: a lot
//==========================================================================
DWORD WINAPI DEV_InjectThread()
{
ManyMouseEvent event; // hold current input event (movement, buttons, ect)
memset(&DEVICE, 0, sizeof(DEVICE)); // clear device struct
int checkwindowtick = 0; // check if emulator window is in focus
int togglebuffer = 0; // buffer cool down for mouse toggle
int acceptalldevices = 0; // accept all device input (used if only 1 player is active)
unsigned char lockmousecounter = 0; // limit SetCursorPos execution
while(ManyMouse_PollEvent(&event)) // flush message pump (max messages is 1024)
{
continue;
}
while(!stopthread)
{
if(mousetoggle && lockmousecounter % (emuoverclock ? TICKRATE_STOCK : TICKRATE_OC) == 0) // don't execute every tick
SetCursorPos(lockpos.x, lockpos.y); // set mouse position to lock position
lockmousecounter++; // overflow pseudo-counter
if(togglebuffer > 0)
togglebuffer--;
for(int player = PLAYER1; player < ALLPLAYERS; player++)
{
DEVICE[player].XPOS = 0, DEVICE[player].YPOS = 0; // reset mouse input
if(DEVICE[player].WHEEL <= 1) // mouse wheel is not an instant key - treat with cooldown and turn button off once cooled off
{
DEVICE[player].WHEEL = 0;
for(int button = 0; button < TOTALBUTTONS; button++) // reset wheel scroll once cooled down
{
if(PROFILE[player].BUTTONPRIM[button] == VK_WHEELUP || PROFILE[player].BUTTONPRIM[button] == VK_WHEELDOWN || PROFILE[player].BUTTONPRIM[button] == VK_WHEELLEFT || PROFILE[player].BUTTONPRIM[button] == VK_WHEELRIGHT)
DEVICE[player].BUTTONPRIM[button] = 0;
if(PROFILE[player].BUTTONSEC[button] == VK_WHEELUP || PROFILE[player].BUTTONSEC[button] == VK_WHEELDOWN || PROFILE[player].BUTTONSEC[button] == VK_WHEELLEFT || PROFILE[player].BUTTONSEC[button] == VK_WHEELRIGHT)
DEVICE[player].BUTTONSEC[button] = 0;
}
}
else
DEVICE[player].WHEEL--;
}
while(ManyMouse_PollEvent(&event))
{
for(int player = PLAYER1; player < ALLPLAYERS; player++)
{
if(PROFILE[player].SETTINGS[CONFIG] == DISABLED) // don't check for disabled players
continue;
acceptalldevices = ONLY1PLAYERACTIVE; // do not filter devices if only one player is active
if(PROFILE[player].SETTINGS[MOUSE] == (int)event.device || acceptalldevices) // mouse movement
{
if(event.type == MANYMOUSE_EVENT_RELMOTION && mousetoggle)
{
if(event.item == 0)
DEVICE[player].XPOS += event.value;
else
DEVICE[player].YPOS += event.value;
}
if(event.type == MANYMOUSE_EVENT_BUTTON) // key presses
{
for(int button = 0; button < TOTALBUTTONS; button++)
{
int offset = event.item > 1 ? 2 : 1; // mouse button needs offset to sync with VK table (left click + offset = 0x01 aka VK_LBUTTON and right click + offset = 0x02 aka VK_RBUTTON)
if(PROFILE[player].BUTTONPRIM[button] == (int)event.item + offset)
DEVICE[player].BUTTONPRIM[button] = event.value;
if(PROFILE[player].BUTTONSEC[button] == (int)event.item + offset)
DEVICE[player].BUTTONSEC[button] = event.value;
}
}
if(event.type == MANYMOUSE_EVENT_SCROLL) // mouse wheel
{
for(int button = 0; button < TOTALBUTTONS; button++)
{
if(event.item == 0) // if VK_WHEELUP/VK_WHEELDOWN
{
if(event.value > 0 && PROFILE[player].BUTTONPRIM[button] == VK_WHEELUP || event.value < 0 && PROFILE[player].BUTTONPRIM[button] == VK_WHEELDOWN)
DEVICE[player].BUTTONPRIM[button] = event.value != 0;
if(event.value > 0 && PROFILE[player].BUTTONSEC[button] == VK_WHEELUP || event.value < 0 && PROFILE[player].BUTTONSEC[button] == VK_WHEELDOWN)
DEVICE[player].BUTTONSEC[button] = event.value != 0;
}
else // if VK_WHEELRIGHT/VK_WHEELLEFT
{
if(event.value > 0 && PROFILE[player].BUTTONPRIM[button] == VK_WHEELLEFT || event.value < 0 && PROFILE[player].BUTTONPRIM[button] == VK_WHEELRIGHT)
DEVICE[player].BUTTONPRIM[button] = event.value != 0;
if(event.value > 0 && PROFILE[player].BUTTONSEC[button] == VK_WHEELLEFT || event.value < 0 && PROFILE[player].BUTTONSEC[button] == VK_WHEELRIGHT)
DEVICE[player].BUTTONSEC[button] = event.value != 0;
}
}
DEVICE[player].WHEEL = 16; // hold button down for 32ms/64ms (non-oc emu need longer buffer because they run at lower framerate)
}
}
if(event.type == MANYMOUSE_EVENT_KEYBOARD && (PROFILE[player].SETTINGS[KEYBOARD] == (int)event.device || acceptalldevices))
{
for(int button = 0; button < TOTALBUTTONS; button++) // check for key presses
{
if(PROFILE[player].BUTTONPRIM[button] == (int)event.item)
DEVICE[player].BUTTONPRIM[button] = event.value;
if(PROFILE[player].BUTTONSEC[button] == (int)event.item)
DEVICE[player].BUTTONSEC[button] = event.value;
}
if(mousetogglekey == (int)event.item && event.value && !togglebuffer && windowactive) // only toggle on press and if window is active
{
mousetoggle = !mousetoggle;
GetCursorPos(&lockpos);
togglebuffer = 100 / TICKRATE; // buffer for 100ms
if(mouselockonfocus) // if user presses mouse toggle key while lock on focus is on, increase buffer size before mouse is relocked so user can temporarily control mouse to close game/change settings
togglebuffer *= 15;
}
}
}
}
if(checkwindowtick > (500 / TICKRATE)) // poll every 500ms
{
checkwindowtick = 0;
if((mouseunlockonloss || !mousetoggle) && emulatorwindow != GetForegroundWindow()) // window is inactive
{
memset(&DEVICE, 0, sizeof(DEVICE)); // reset player input
GAME_Inject(); // ship empty input to game
windowactive = 0, mousetoggle = 0, togglebuffer = 0;
}
else // emu window is in focus
{
windowactive = 1;
if(mouselockonfocus && !mousetoggle && !togglebuffer) // if mouselockonfocus is on and window was refocused/mouse toggle is off, turn on mouse toggle
{
mousetoggle = 1;
GetCursorPos(&lockpos);
}
}
}
else
checkwindowtick++;
if(windowactive && GAME_Status() && !configdialogopen) // if emulator is focused, game is valid and config dialog isn't open
GAME_Inject(); // send input to game driver
Sleep(TICKRATE);
}
GAME_Quit(); // reset game driver's global variables
return 0;
}
//==========================================================================
// Purpose: Returns a single key
//==========================================================================
int DEV_ReturnKey(void)
{
int key = 0;
ManyMouseEvent event; // hold current input event (movement, buttons, ect)
while(ManyMouse_PollEvent(&event))
{
if(event.type == MANYMOUSE_EVENT_BUTTON)
{
if(event.item < 2)
key = event.item ? VK_RBUTTON : VK_LBUTTON;
else if(event.item == 2)
key = VK_MBUTTON;
else if(event.item == 3)
key = VK_XBUTTON1;
else
key = VK_XBUTTON2;
}
else if(event.type == MANYMOUSE_EVENT_SCROLL)
{
if(event.item == 0)
key = event.value > 0 ? VK_WHEELUP : VK_WHEELDOWN;
else
key = event.value > 0 ? VK_WHEELRIGHT : VK_WHEELLEFT;
}
else if(event.type == MANYMOUSE_EVENT_KEYBOARD)
key = event.item;
}
return ClampInt(key, 0, 0xFF); // sanity check key return
}
//==========================================================================
// Purpose: Returns device id of detected input
//==========================================================================
int DEV_ReturnDeviceID(const int devicetype)
{
ManyMouseEvent event; // hold current input event (movement, buttons, ect)
while(ManyMouse_PollEvent(&event))
if(devicetype == MOUSETYPE && (event.type == MANYMOUSE_EVENT_BUTTON || event.type == MANYMOUSE_EVENT_SCROLL) || devicetype == KEYBOARDTYPE && event.type == MANYMOUSE_EVENT_KEYBOARD)
return event.device;
return -1;
}
//==========================================================================
// Purpose: Returns the device name given a type
//==========================================================================
const char *DEV_Name(const int id)
{
if(ManyMouse_DeviceName(id, MOUSETYPE) != NULL)
return ManyMouse_DeviceName(id, MOUSETYPE);
if(ManyMouse_DeviceName(id, KEYBOARDTYPE) != NULL)
return ManyMouse_DeviceName(id, KEYBOARDTYPE);
return NULL;
}
//==========================================================================
// Purpose: Wraps ManyMouse device name and returns the device type
//==========================================================================
int DEV_Type(const int id)
{
return ManyMouse_DeviceName(id, MOUSETYPE) != NULL ? MOUSETYPE : KEYBOARDTYPE; // 0 mouse : 1 keyboard
}
//==========================================================================
// Purpose: Returns the index id within a type (for converting to device combobox)
//==========================================================================
int DEV_TypeIndex(const int id)
{
int kbcount = -1, mscount = -1;
for(int index = 0; index < DEV_Init(); index++)
{
if(DEV_Type(index) == MOUSETYPE)
mscount++;
else
kbcount++;
if(index == id)
return DEV_Type(index) == MOUSETYPE ? mscount : kbcount;
}
return 0;
}
//==========================================================================
// Purpose: Converts a type index id to its real id (for converting from device combobox)
//==========================================================================
int DEV_TypeID(const int id, const int devicetype)
{
int kbcount = -1, mscount = -1;
for(int index = 0; index < DEV_Init(); index++)
{
if(DEV_Type(index) == MOUSETYPE)
mscount++;
else
kbcount++;
if(id == mscount && devicetype == MOUSETYPE || id == kbcount && devicetype == KEYBOARDTYPE)
return index;
}
return 0;
}
-30
View File
@@ -1,30 +0,0 @@
//==========================================================================
// Mouse Injector Plugin
//==========================================================================
// Copyright (C) 2016-2021 Carnivorous
// All rights reserved.
//
// Mouse Injector is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, visit http://www.gnu.org/licenses/gpl-2.0.html
//==========================================================================
extern int windowactive;
extern int DEV_Init(void);
extern void DEV_Quit(void);
extern DWORD WINAPI DEV_InjectThread();
extern int DEV_ReturnKey(void);
extern int DEV_ReturnDeviceID(const int devicetype);
extern const char *DEV_Name(const int id);
extern int DEV_Type(const int id);
extern int DEV_TypeIndex(const int id);
extern int DEV_TypeID(const int id, const int devicetype);
-205
View File
@@ -1,205 +0,0 @@
//==========================================================================
// Mouse Injector Plugin
//==========================================================================
// Copyright (C) 2016-2021 Carnivorous
// All rights reserved.
//
// Mouse Injector is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, visit http://www.gnu.org/licenses/gpl-2.0.html
//==========================================================================
#ifdef ADD_DISCORD_PRESENCE
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "global.h"
#include "discord.h"
#include "maindll.h"
#include "games/game.h"
#include "games/memory.h"
#include "./discord/discord_rpc.h"
#define ROMCRC1 0x10
#define ROMCRC2 0x14
#define ROMNAME 0x28
// GOLDENEYE ADDRESSES
#define GE_stageid 0x8002A8F4
#define GE_difficulty 0x8002A8FC
#define GE_camera 0x80036494
#define GE_pause 0x80048370
#define GE_menupage 0x8002A8C0
#define GE_sptime 0x80079A20
#define GE_mptime 0x80048394
#define GE_gamemode 0x8002A8F0
#define GECRC1 0xDCBC50D1
#define GECRC2 0x09FD1AA3
// PERFECT DARK ADDRESSES
#define PD_stageid 0x800624E4
#define PD_difficulty 0x80084020
#define PD_camera 0x8009A26C
#define PD_pause 0x80084014
#define PD_mppause 0x800ACBA6
#define PD_joannadata 0x8009A024
#define PD_sptime 0x801BD21C - 0x801BB6A0
#define PD_mptime 0x80084024
#define PDCRC1 0x41F2B98F
#define PDCRC2 0xB458B466
static const char gestagenames[0x3A][0x0C] = {"", "", "", "", "", "", "", "", "", "Bunker I", "", "", "", "", "", "", "", "", "", "", "Silo", "", "Statue Park", "Control", "Archives", "Train", "Frigate", "Bunker II", "Aztec", "Streets", "Depot", "Complex", "Egypt", "Dam", "Facility", "Runway", "Surface I", "Jungle", "Temple", "Caverns", "Citadel", "Cradle", "", "Surface II", "", "Basement", "Stack", "", "Library", "", "Caves", "", "", "", "Credits", "", "", ""}; // stage names
static const char gedifficulty[0x04][0x0D] = {"Agent", "Secret Agent", "00 Agent", "007"}; // difficulty string
static const char pdstagenames[0x51][0x17] = {"", "", "", "", "", "", "", "", "", "Maian SOS", "", "", "", "", "", "", "", "", "", "", "", "", "WAR!", "Ravine", "", "A51 Escape", "", "", "Crash Site", "Chicago", "G5 Building", "Complex", "G5 Building", "Pelagic II", "dataDyne Extraction", "", "", "Temple", "Carrington Institute", "Air Base", "", "Pipes", "Skedar Ruins", "", "Carrington Villa", "Carrington Institute", "", "A51 Infiltration", "dataDyne Defection", "Air Force One", "Skedar", "dataDyne Investigation", "Attack Ship", "A51 Rescue", "", "Mr. Blonde's Revenge", "Deep Sea", "Base", "", "Area 52", "Warehouse", "Car Park", "", "", "", "Ruins", "Sewers", "Felicity", "Fortress", "Villa", "", "Grid", "", "", "", "", "", "", "", "Duel"}; // stage names
static const char pddifficulty[0x03][0x0E] = {"Agent", "Secret Agent", "Perfect Agent"}; // difficulty string
static const int pdmpstageids[0x10] = {0x32, 0x29, 0x17, 0x20, 0x42, 0x3C, 0x47, 0x41, 0x3B, 0x39, 0x44, 0x45, 0x3D, 0x25, 0x1F, 0x43}; // multiplayer stage ids
static DiscordRichPresence presence; // presence struct for update function
static int alreadyexec = 0; // has init already exec?
static char thumbnailid[0x5]; // holds thumbnail id
static void DRP_Init(void);
void DRP_Update(void);
void DRP_Quit(void);
//==========================================================================
// Purpose: init discord rich presence
//==========================================================================
static void DRP_Init(void)
{
Discord_Initialize("454158757262262272", NULL, 1, NULL);
alreadyexec = 1;
}
//==========================================================================
// Purpose: updates discord rich presence
// Changed Globals: presence struct
//==========================================================================
void DRP_Update(void)
{
if(!alreadyexec)
DRP_Init();
memset(&presence, 0, sizeof(presence)); // set presence struct to 0
if(GAME_Name() != NULL)
{
if(EMU_ReadROM(ROMCRC1) == GECRC1 && EMU_ReadROM(ROMCRC2) == GECRC2) // check if official GE rom
{
presence.largeImageKey = "ge"; // large default icon (not in-game)
presence.largeImageText = "GoldenEye 007";
if(EMU_ReadInt(GE_menupage) == 11) // if in-game
{
presence.smallImageKey = "geingame"; // set small icon
presence.details = gestagenames[ClampInt(EMU_ReadInt(GE_stageid), 0x00, 0x39)]; // set details to map name (after clamping)
int mpflag = EMU_ReadInt(GE_gamemode) == 1; // set to 1 if gamemode is multiplayer (0 = sp, 1 = mp, 2 = cheats)
presence.state = !mpflag ? gedifficulty[ClampInt(EMU_ReadInt(GE_difficulty), 0, 3)] : "Multiplayer"; // set difficulty/multiplayer to state
if(EMU_ReadInt(GE_pause) == 0 && (EMU_ReadInt(GE_camera) == 4 || EMU_ReadInt(GE_camera) == 0)) // if in gameplay mode (not intro swirl) and not paused, calculate time
{
time_t currenttime = time(NULL); // get current time from OS
presence.startTimestamp = currenttime - (EMU_ReadInt(!mpflag ? GE_sptime : GE_mptime) / 60); // convert in-game time (60 Hz) to seconds and subtract from current time to get starting time for current map
}
sprintf(thumbnailid, "ge%1.2x", EMU_ReadInt(GE_stageid)); // set thumbnail id
presence.largeImageKey = thumbnailid;
}
else // not in-game
{
if(EMU_ReadInt(GE_menupage) >= -1 && EMU_ReadInt(GE_menupage) <= 4) // intro range
presence.details = "Intro";
else if(EMU_ReadInt(GE_menupage) == 24) // character credits
presence.details = "Credits";
else // in menu
presence.details = "In Main Menu";
}
}
else if(EMU_ReadROM(ROMCRC1) == PDCRC1 && EMU_ReadROM(ROMCRC2) == PDCRC2) // check if official PD rom
{
presence.largeImageKey = "pd"; // large default icon (not in-game)
presence.largeImageText = "Perfect Dark";
if(EMU_ReadInt(PD_stageid) >= 0x09 && EMU_ReadInt(PD_stageid) < 0x51) // if stage id is within char array
{
presence.smallImageKey = "pdingame"; // set small icon
presence.details = pdstagenames[EMU_ReadInt(PD_stageid)]; // set details to map name
if(EMU_ReadInt(PD_stageid) != 0x26) // if level isn't carrington institute
{
int mpflag = 0;
for(int index = 0; index < 0x10; index++) // compare current stage id to list of mp stage ids
if(pdmpstageids[index] == EMU_ReadInt(PD_stageid))
mpflag = 1;
presence.state = !mpflag ? pddifficulty[ClampInt(EMU_ReadInt(PD_difficulty), 0, 2)] : "Combat Simulator"; // set difficulty/combat simulator to state
if(EMU_ReadInt(PD_pause) == 0 && (EMU_ReadShort(PD_mppause) & 0xFF00) == 0 && (EMU_ReadInt(PD_camera) == 1 || EMU_ReadInt(PD_camera) == 7)) // if in gameplay mode (not cutscene) and not paused, calculate time
{
time_t currenttime = time(NULL); // get current time from OS
int gametime;
if(!mpflag)
gametime = EMU_ReadInt(EMU_ReadInt(PD_joannadata) + PD_sptime) / 60; // convert in-game SP time (60 Hz) to seconds (SP time is part of player struct)
else
gametime = EMU_ReadInt(PD_mptime) / 60; // convert in-game MP time (60 Hz) to seconds
presence.startTimestamp = currenttime - gametime; // subtract from current time to get starting time for current map
}
}
sprintf(thumbnailid, "pd%1.2x", EMU_ReadInt(PD_stageid)); // set thumbnail id
presence.largeImageKey = thumbnailid;
}
else if(EMU_ReadInt(PD_stageid) == -1)
presence.details = "Intro";
else if(EMU_ReadInt(PD_stageid) == 0x5C) // if credits
presence.state = "Credits";
}
else // user is running a rom hack
{
switch(EMU_ReadROM(ROMNAME))
{
case 0x45522020: // if GF rom hack
presence.largeImageKey = "gfcustom";
presence.largeImageText = "Goldfinger 64";
break;
case 0x65205820: // if GEX rom hack
presence.largeImageKey = "gexcustom";
presence.largeImageText = "GoldenEye X";
break;
case 0x45202020: // if GE rom hack
presence.largeImageKey = "custom";
presence.largeImageText = "GoldenEye 007 (ROM Hack)";
break;
default: // assume PD rom hack
presence.largeImageKey = "pdcustom";
presence.largeImageText = "Perfect Dark (ROM Hack)";
break;
}
presence.details = presence.largeImageText;
}
}
else
{
presence.largeImageKey = "logo"; // default 1964 icon
presence.largeImageText = "N64 Emulator for GE/PD";
presence.details = "Not In-Game";
}
Discord_UpdatePresence(&presence);
}
//==========================================================================
// Purpose: safely shutdown discord rich presence
// Changed Globals: alreadyexec
//==========================================================================
void DRP_Quit(void)
{
Discord_ClearPresence();
Discord_Shutdown();
alreadyexec = 0;
}
#else
//==========================================================================
// Purpose: dummy functions for non-drp build
//==========================================================================
void DRP_Update(void)
{
return;
}
void DRP_Quit(void)
{
return;
}
#endif
-21
View File
@@ -1,21 +0,0 @@
//==========================================================================
// Mouse Injector Plugin
//==========================================================================
// Copyright (C) 2016-2021 Carnivorous
// All rights reserved.
//
// Mouse Injector is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, visit http://www.gnu.org/licenses/gpl-2.0.html
//==========================================================================
extern void DRP_Update(void);
extern void DRP_Quit(void);
Binary file not shown.
@@ -1,26 +0,0 @@
#pragma once
#if defined(DISCORD_DYNAMIC_LIB)
# if defined(_WIN32)
# if defined(DISCORD_BUILDING_SDK)
# define DISCORD_EXPORT __declspec(dllexport)
# else
# define DISCORD_EXPORT __declspec(dllimport)
# endif
# else
# define DISCORD_EXPORT __attribute__((visibility("default")))
# endif
#else
# define DISCORD_EXPORT
#endif
#ifdef __cplusplus
extern "C" {
#endif
DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command);
DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId, const char* steamId);
#ifdef __cplusplus
}
#endif
@@ -1,87 +0,0 @@
#pragma once
#include <stdint.h>
// clang-format off
#if defined(DISCORD_DYNAMIC_LIB)
# if defined(_WIN32)
# if defined(DISCORD_BUILDING_SDK)
# define DISCORD_EXPORT __declspec(dllexport)
# else
# define DISCORD_EXPORT __declspec(dllimport)
# endif
# else
# define DISCORD_EXPORT __attribute__((visibility("default")))
# endif
#else
# define DISCORD_EXPORT
#endif
// clang-format on
#ifdef __cplusplus
extern "C" {
#endif
typedef struct DiscordRichPresence {
const char* state; /* max 128 bytes */
const char* details; /* max 128 bytes */
int64_t startTimestamp;
int64_t endTimestamp;
const char* largeImageKey; /* max 32 bytes */
const char* largeImageText; /* max 128 bytes */
const char* smallImageKey; /* max 32 bytes */
const char* smallImageText; /* max 128 bytes */
const char* partyId; /* max 128 bytes */
int partySize;
int partyMax;
const char* matchSecret; /* max 128 bytes */
const char* joinSecret; /* max 128 bytes */
const char* spectateSecret; /* max 128 bytes */
int8_t instance;
} DiscordRichPresence;
typedef struct DiscordUser {
const char* userId;
const char* username;
const char* discriminator;
const char* avatar;
} DiscordUser;
typedef struct DiscordEventHandlers {
void (*ready)(const DiscordUser* request);
void (*disconnected)(int errorCode, const char* message);
void (*errored)(int errorCode, const char* message);
void (*joinGame)(const char* joinSecret);
void (*spectateGame)(const char* spectateSecret);
void (*joinRequest)(const DiscordUser* request);
} DiscordEventHandlers;
#define DISCORD_REPLY_NO 0
#define DISCORD_REPLY_YES 1
#define DISCORD_REPLY_IGNORE 2
DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
DiscordEventHandlers* handlers,
int autoRegister,
const char* optionalSteamId);
DISCORD_EXPORT void Discord_Shutdown(void);
/* checks for incoming messages, dispatches callbacks */
DISCORD_EXPORT void Discord_RunCallbacks(void);
/* If you disable the lib starting its own io thread, you'll need to call this from your own */
#ifdef DISCORD_DISABLE_IO_THREAD
DISCORD_EXPORT void Discord_UpdateConnection(void);
#endif
DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence* presence);
DISCORD_EXPORT void Discord_ClearPresence(void);
DISCORD_EXPORT void Discord_Respond(const char* userid, /* DISCORD_REPLY_ */ int reply);
DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* handlers);
#ifdef __cplusplus
} /* extern "C" */
#endif
-85
View File
@@ -1,85 +0,0 @@
//==========================================================================
// Mouse Injector Plugin
//==========================================================================
// Copyright (C) 2016-2021 Carnivorous
// All rights reserved.
//
// Mouse Injector is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, visit http://www.gnu.org/licenses/gpl-2.0.html
//==========================================================================
#include <stdlib.h>
#include "game.h"
extern const GAMEDRIVER *GAME_GOLDENEYE007;
extern const GAMEDRIVER *GAME_PERFECTDARK;
static const GAMEDRIVER **GAMELIST[] =
{
&GAME_GOLDENEYE007,
&GAME_PERFECTDARK
};
static const GAMEDRIVER *CURRENT_GAME = NULL;
static const int upper = (sizeof(GAMELIST) / sizeof(GAMELIST[0]));
int GAME_Status(void);
const char *GAME_Name(void);
void GAME_Inject(void);
void GAME_Quit(void);
//==========================================================================
// Purpose: check all game interfaces for game
//==========================================================================
int GAME_Status(void)
{
if(CURRENT_GAME != NULL) // if any game has been detected previously
{
if(CURRENT_GAME->Status()) // check if game is still active, else check every supported driver
return 1;
CURRENT_GAME = NULL;
}
const GAMEDRIVER *THIS_GAME;
for(int i = 0; (i < upper) && (CURRENT_GAME == NULL); i++)
{
THIS_GAME = *(GAMELIST[i]);
if(THIS_GAME != NULL && THIS_GAME->Status())
CURRENT_GAME = THIS_GAME;
}
return (CURRENT_GAME != NULL);
}
//==========================================================================
// Purpose: return game driver name
//==========================================================================
const char *GAME_Name(void)
{
if(CURRENT_GAME != NULL)
return CURRENT_GAME->Name;
return NULL;
}
//==========================================================================
// Purpose: inject via game driver
//==========================================================================
void GAME_Inject(void)
{
if(CURRENT_GAME != NULL)
CURRENT_GAME->Inject();
}
//==========================================================================
// Purpose: quit game driver
//==========================================================================
void GAME_Quit(void)
{
if(CURRENT_GAME != NULL)
CURRENT_GAME->Quit();
CURRENT_GAME = NULL;
}
-31
View File
@@ -1,31 +0,0 @@
//==========================================================================
// Mouse Injector Plugin
//==========================================================================
// Copyright (C) 2016-2021 Carnivorous
// All rights reserved.
//
// Mouse Injector is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, visit http://www.gnu.org/licenses/gpl-2.0.html
//==========================================================================
typedef struct
{
const char *Name;
int (*Status)(void);
void (*Inject)(void);
void (*Quit)(void);
} GAMEDRIVER;
extern int GAME_Status(void);
extern const char *GAME_Name(void);
extern void GAME_Inject(void);
extern void GAME_Quit(void);
-383
View File
@@ -1,383 +0,0 @@
//==========================================================================
// Mouse Injector Plugin
//==========================================================================
// Copyright (C) 2016-2021 Carnivorous
// All rights reserved.
//
// Mouse Injector is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, visit http://www.gnu.org/licenses/gpl-2.0.html
//==========================================================================
#include <math.h>
#include "../global.h"
#include "../maindll.h"
#include "game.h"
#include "memory.h"
#define GUNAIMLIMIT 6.879164696 // 0x40DC221E
#define CROSSHAIRLIMIT 5.159373283 // 0x40A51996
#define TANKXROTATIONLIMIT 6.283185005 // 0x40C90FDA
#define PI 3.1415927 // 0x40490FDB
// GOLDENEYE ADDRESSES - OFFSET ADDRESSES BELOW (REQUIRES PLAYERBASE TO USE)
#define GE_stanceflag 0x800D2FFC - 0x800D2F60
#define GE_deathflag 0x800D3038 - 0x800D2F60
#define GE_camx 0x800D30A8 - 0x800D2F60
#define GE_camy 0x800D30B8 - 0x800D2F60
#define GE_fov 0x800D4124 - 0x800D2F60
#define GE_crosshairx 0x800D3F50 - 0x800D2F60
#define GE_crosshairy 0x800D3F54 - 0x800D2F60
#define GE_watch 0x800D3128 - 0x800D2F60
#define GE_gunx 0x800D3F64 - 0x800D2F60
#define GE_guny 0x800D3F68 - 0x800D2F60
#define GE_aimingflag 0x800D3084 - 0x800D2F60
#define GE_currentweapon 0x800D37D0 - 0x800D2F60
#define GE_multipausemenu 0x800A9D24 - 0x800A7360
// STATIC ADDRESSES BELOW
#define BONDDATA(X) (unsigned int)EMU_ReadInt(0x80079EE0 + (X * 0x4)) // player pointer address (0x4 offset for each players)
#define GE_camera 0x80036494 // camera flag (0 = multiplayer, 1 = map overview, 2 = start flyby, 3 = in flyby, 4 = player in control, 5 = trigger restart map)
#define GE_exit 0x800364B0 // exit flag (0 = disable controls, 1 = enable controls)
#define GE_pause 0x80048370 // pause flag (1 = GE is paused)
#define GE_menupage 0x8002A8C0 // menu page id
#define GE_menux 0x8002A908 // crosshair menu cursor x axis
#define GE_menuy 0x8002A90C // crosshair menu cursor y axis
#define GE_tankxrot 0x80036484 // tank x rotation
#define GE_tankflag 0x80036448 // tank flag (0 = walking, 1 = in-tank)
#define GE_matchended 0x8008C700 // multiplayer match flag
#define GE_defaultratio 0x80055264 // 16:9 ratio default
#define GE_defaultratiocrosshair 0x0009F198 // 16:9 crosshair ratio default (rom)
#define GE_defaultfov 0x000B78BC // field of view default (rom)
#define GE_defaultfovinit 0x000CF838 // field of view init value (rom)
#define GE_defaultfovzoom 0x000B78DC // field of view default for zoom (rom)
#define GE_defaultzoomspeed 0x8004F1A8 // default zoom speed
#define GE_showcrosshair 0x0009F128 // show crosshair code (rom)
#define GE_crosshairimage 0x0029DE8C // crosshair image (rom)
#define GE_introcounter 0x8002A8CC // counter for intro
#define GE_seenintroflag 0x8002A930 // seen intro flag
#define GE_controlstyle 0x000D98FC // instruction reads the current controller style (rom)
#define GE_reversepitch 0x000D9970 // instruction reads the current reverse pitch option (rom)
#define GE_pickupyaxisthreshold 0x800532E0 // y axis threshold on picking up weapons
#define GE_weaponypos 0x8003249C // y axis position for view models
#define GE_weaponzpos (GE_weaponypos + 4) // z axis position for view models
static unsigned int playerbase[4] = {0}; // current player's bonddata address
static int safetocrouch[4] = {1, 1, 1, 1}, safetostand[4] = {0}, crouchstance[4] = {0}; // used for crouch toggle (limits tick-tocking)
static float crosshairposx[4], crosshairposy[4], aimx[4], aimy[4];
int GE_Status(void);
void GE_Inject(void);
static void GE_Crouch(const int player);
#define GE_ResetCrouchToggle(X) safetocrouch[X] = 1, safetostand[X] = 0, crouchstance[X] = 0 // reset crouch toggle bind
static void GE_AimMode(const int player, const int aimingflag, const float fov, const float basefov);
static void GE_Controller(void);
static void GE_InjectHacks(void);
void GE_Quit(void);
static const GAMEDRIVER GAMEDRIVER_INTERFACE =
{
"GoldenEye 007",
GE_Status,
GE_Inject,
GE_Quit
};
const GAMEDRIVER *GAME_GOLDENEYE007 = &GAMEDRIVER_INTERFACE;
//==========================================================================
// Purpose: returns a value, which is then used to check what game is running in game.c
// Q: What is happening here?
// A: We look up some static addresses and if the values are within the expected ranges the program can assume that the game is currently running
//==========================================================================
int GE_Status(void)
{
const int ge_camera = EMU_ReadInt(GE_camera), ge_page = EMU_ReadInt(GE_menupage), ge_pause = EMU_ReadInt(GE_pause), ge_exit = EMU_ReadInt(GE_exit);
const float ge_crosshairx = EMU_ReadFloat(GE_menux), ge_crosshairy = EMU_ReadFloat(GE_menuy);
return (ge_camera >= 0 && ge_camera <= 10 && ge_page >= -1 && ge_page <= 25 && ge_pause >= 0 && ge_pause <= 1 && ge_exit >= 0 && ge_exit <= 1 && ge_crosshairx >= 20 && ge_crosshairx <= 420 && ge_crosshairy >= 20 && ge_crosshairy <= 310); // if GoldenEye 007 is current game
}
//==========================================================================
// Purpose: calculate mouse movement and inject into current game
// Changes Globals: safetocrouch, safetostand, crouchstance
// Q: Could you explain !aimingflag ? 10.0f : 40.0f
// A: While the player is aiming weapon sway will be reduced by 75%. While this is not in the original design of GE/PD I feel it gives a legitimate advantage for aiming instead of only making the crosshair visible
// Q: Could you explain basefov = fov > 60.0f ? (float)OVERRIDEFOV : 60.0f
// A: For weapons that zoom, the fov is lower than 60 - when this happens we compute our calculations using 60 as a base instead of the override fov. This is to prevent weapons from becoming too sluggish to move while zoomed with a high override fov
// Q: Could you explain if(aimingflag) gunx /= emuoverclock ? 1.03f : 1.07f, crosshairx /= emuoverclock ? 1.03f : 1.07f;
// A: GE_InjectHacks() disables the engine from overwriting the crosshair pos and gun rot - this is so aiming is jitter free. But it removed the auto centering code while aiming. If the player turns off cursor aiming for GE, the crosshair and gun will no longer move back to the center (it'll float to the corners of the screen). This if statement will emulate the centering code. The emuoverclock condition will make the scale the same - regardless of overclock or stock (inject exec at higher tickrate if overclocked).
//==========================================================================
void GE_Inject(void)
{
if(EMU_ReadInt(GE_menupage) < 1) // hacks can only be injected at boot sequence before code blocks are cached, so inject until the main menu
GE_InjectHacks();
const int camera = EMU_ReadInt(GE_camera);
const int exit = EMU_ReadInt(GE_exit);
const int pause = EMU_ReadInt(GE_pause);
const int menupage = EMU_ReadInt(GE_menupage);
const int tankflag = EMU_ReadInt(GE_tankflag);
const int mproundend = EMU_ReadInt(GE_matchended);
for(int player = PLAYER1; player < ALLPLAYERS; player++)
{
if(PROFILE[player].SETTINGS[CONFIG] == DISABLED) // bypass disabled players
continue;
playerbase[player] = BONDDATA(player);
const int dead = EMU_ReadInt(playerbase[player] + GE_deathflag);
const int watch = EMU_ReadInt(playerbase[player] + GE_watch);
const int aimingflag = EMU_ReadInt(playerbase[player] + GE_aimingflag);
const int mppausemenu = EMU_ReadInt(playerbase[player] + GE_multipausemenu);
const int cursoraimingflag = PROFILE[player].SETTINGS[GEAIMMODE] && aimingflag;
const float fov = EMU_ReadFloat(playerbase[player] + GE_fov);
const float basefov = fov > 60.0f ? (float)OVERRIDEFOV : 60.0f;
const float mouseaccel = PROFILE[player].SETTINGS[ACCELERATION] ? sqrt(DEVICE[player].XPOS * DEVICE[player].XPOS + DEVICE[player].YPOS * DEVICE[player].YPOS) / TICKRATE / 12.0f * PROFILE[player].SETTINGS[ACCELERATION] : 0;
const float sensitivity = PROFILE[player].SETTINGS[SENSITIVITY] / 40.0f * fmax(mouseaccel, 1);
const float gunsensitivity = sensitivity * (PROFILE[player].SETTINGS[CROSSHAIR] / 2.5f);
float camx = EMU_ReadFloat(playerbase[player] + GE_camx), camy = EMU_ReadFloat(playerbase[player] + GE_camy);
if(camx >= 0 && camx <= 360 && camy >= -90 && camy <= 90 && fov >= 1 && fov <= FOV_MAX && dead == 0 && watch == 0 && pause == 0 && (camera == 4 || camera == 0) && exit == 1 && menupage == 11 && !mproundend && !mppausemenu) // if safe to inject
{
GE_AimMode(player, cursoraimingflag, fov, basefov);
if(!tankflag) // player is on foot
{
GE_Crouch(player); // only allow crouching if player is not in tank
if(!cursoraimingflag) // if not aiming (or geaimmode is off)
camx += DEVICE[player].XPOS / 10.0f * sensitivity * (fov / basefov); // regular mouselook calculation
else
camx += aimx[player] * (fov / basefov); // scroll screen with aimx/aimy
while(camx < 0)
camx += 360;
while(camx >= 360)
camx -= 360;
EMU_WriteFloat(playerbase[player] + GE_camx, camx);
}
else // player is in tank
{
GE_ResetCrouchToggle(player); // reset crouch toggle if in tank
float tankx = EMU_ReadFloat(GE_tankxrot);
if(!cursoraimingflag || EMU_ReadInt(playerbase[player] + GE_currentweapon) == 32) // if not aiming (or geaimmode is off) or player is driving tank with tank equipped as weapon, then use regular mouselook calculation
tankx += DEVICE[player].XPOS / 10.0f * sensitivity / (360 / TANKXROTATIONLIMIT * 2.5) * (fov / basefov);
else
tankx += aimx[player] / (360 / TANKXROTATIONLIMIT * 2.5) * (fov / basefov);
while(tankx < 0)
tankx += TANKXROTATIONLIMIT;
while(tankx >= TANKXROTATIONLIMIT)
tankx -= TANKXROTATIONLIMIT;
EMU_WriteFloat(GE_tankxrot, tankx);
}
if(!cursoraimingflag)
camy += (!PROFILE[player].SETTINGS[INVERTPITCH] ? -DEVICE[player].YPOS : DEVICE[player].YPOS) / 10.0f * sensitivity * (fov / basefov);
else
camy += -aimy[player] * (fov / basefov);
camy = ClampFloat(camy, tankflag ? -20 : -90, 90); // tank limits player from looking down -20
EMU_WriteFloat(playerbase[player] + GE_camy, camy);
if(PROFILE[player].SETTINGS[CROSSHAIR] && !cursoraimingflag) // if crosshair movement is enabled and player isn't aiming (don't calculate weapon movement while the player is in aim mode)
{
if(!tankflag)
{
float gunx = EMU_ReadFloat(playerbase[player] + GE_gunx), crosshairx = EMU_ReadFloat(playerbase[player] + GE_crosshairx); // after camera x and y have been calculated and injected, calculate the gun/crosshair movement
gunx += DEVICE[player].XPOS / (!aimingflag ? 10.0f : 40.0f) * gunsensitivity * (fov / basefov) * 0.019f;
crosshairx += DEVICE[player].XPOS / (!aimingflag ? 10.0f : 40.0f) * gunsensitivity * (fov / 4 / (basefov / 4)) * 0.01912f / RATIOFACTOR;
if(aimingflag) // emulate cursor moving back to the center
gunx /= emuoverclock ? 1.03f : 1.07f, crosshairx /= emuoverclock ? 1.03f : 1.07f;
gunx = ClampFloat(gunx, -GUNAIMLIMIT, GUNAIMLIMIT);
crosshairx = ClampFloat(crosshairx, -CROSSHAIRLIMIT, CROSSHAIRLIMIT);
EMU_WriteFloat(playerbase[player] + GE_gunx, gunx);
EMU_WriteFloat(playerbase[player] + GE_crosshairx, crosshairx);
}
if((!tankflag && camy > -90 || tankflag && camy > -20) && camy < 90) // only allow player's gun to pitch within a valid range
{
float guny = EMU_ReadFloat(playerbase[player] + GE_guny), crosshairy = EMU_ReadFloat(playerbase[player] + GE_crosshairy);
guny += (!PROFILE[player].SETTINGS[INVERTPITCH] ? DEVICE[player].YPOS : -DEVICE[player].YPOS) / (!aimingflag ? 40.0f : 20.0f) * gunsensitivity * (fov / basefov) * 0.025f;
crosshairy += (!PROFILE[player].SETTINGS[INVERTPITCH] ? DEVICE[player].YPOS : -DEVICE[player].YPOS) / (!aimingflag ? 40.0f : 20.0f) * gunsensitivity * (fov / 4 / (basefov / 4)) * 0.0225f;
if(aimingflag)
guny /= emuoverclock ? 1.15f : 1.35f, crosshairy /= emuoverclock ? 1.15f : 1.35f;
guny = ClampFloat(guny, -GUNAIMLIMIT, GUNAIMLIMIT);
crosshairy = ClampFloat(crosshairy, -CROSSHAIRLIMIT, CROSSHAIRLIMIT);
EMU_WriteFloat(playerbase[player] + GE_guny, guny);
EMU_WriteFloat(playerbase[player] + GE_crosshairy, crosshairy);
}
}
}
else if(player == PLAYER1 && menupage != 11 && menupage != 23) // if user is in menu (only player 1 can control menu)
{
float menucrosshairx = EMU_ReadFloat(GE_menux), menucrosshairy = EMU_ReadFloat(GE_menuy);
menucrosshairx += DEVICE[player].XPOS / 10.0f * sensitivity * 6;
menucrosshairy += DEVICE[player].YPOS / 10.0f * sensitivity * (400.0f / 290.0f * 6); // y is a little weaker then x in the menu so add more power to make it feel even with x axis
menucrosshairx = ClampFloat(menucrosshairx, 20, 420);
menucrosshairy = ClampFloat(menucrosshairy, 20, 310);
EMU_WriteFloat(GE_menux, menucrosshairx);
EMU_WriteFloat(GE_menuy, menucrosshairy);
}
if(dead || menupage != 11) // if player is dead or in menu, reset crouch toggle
GE_ResetCrouchToggle(player);
}
GE_Controller(); // set controller data
}
//==========================================================================
// Purpose: crouching function for GoldenEye (2 = stand, 1 = kneel (in tank), 0 = crouch)
// Changes Globals: safetocrouch, crouchstance, safetostand
//==========================================================================
static void GE_Crouch(const int player)
{
int crouchheld = DEVICE[player].BUTTONPRIM[CROUCH] || DEVICE[player].BUTTONSEC[CROUCH] || DEVICE[player].BUTTONPRIM[KNEEL] || DEVICE[player].BUTTONSEC[KNEEL];
if(PROFILE[player].SETTINGS[CROUCHTOGGLE]) // check and toggle player stance
{
if(safetocrouch[player] && crouchheld) // standing to crouching
safetocrouch[player] = 0, crouchstance[player] = 1;
else if(!safetocrouch[player] && !crouchheld) // crouch is no longer being held, ready to stand
safetostand[player] = 1;
if(safetostand[player] && crouchheld) // stand up
safetocrouch[player] = 1, crouchstance[player] = 0;
else if(safetostand[player] && safetocrouch[player] && !crouchheld) // crouch key not active, ready to toggle
safetostand[player] = 0;
crouchheld = crouchstance[player];
}
EMU_WriteInt(playerbase[player] + GE_stanceflag, !crouchheld ? 2 : 0); // set in-game stance
}
//==========================================================================
// Purpose: replicate the original aiming system, uses aimx/y to move screen when crosshair is on border of screen
// Changes Globals: crosshairposx, crosshairposy, aimx, aimy
//==========================================================================
static void GE_AimMode(const int player, const int aimingflag, const float fov, const float basefov)
{
const float crosshairx = EMU_ReadFloat(playerbase[player] + GE_crosshairx), crosshairy = EMU_ReadFloat(playerbase[player] + GE_crosshairy), offsetpos[2][33] = {{0, 0, 0, 0, 0.1625, 0.1625, 0.15, 0.5, 0.8, 0.4, 0.5, 0.5, 0.48, 0.9, 0.25, 0.6, 0.6, 0.7, 0.25, 0.15, 0.1625, 0.1625, 0.5, 0.5, 0.9, 0.9, 0, 0, 0, 0, 0, 0.4}, {0, 0, 0, 0, 0.1, 0.1, 0.2, 0.325, 1, 0.3, 0.425, 0.425, 0.45, 0.95, 0.1, 0.55, 0.5, 0.7, 0.25, 0.1, 0.1, 0.1, 0.275, 1, 0.9, 0.8, 0, 0, 0, 0, 0, 0.25}}; // table of X/Y offset for weapons
const int currentweapon = EMU_ReadInt(playerbase[player] + GE_currentweapon);
const float fovratio = fov / basefov, fovmodifier = basefov / 60.f; // basefov is 60 unless override is above 60
const float threshold = 0.72f, speed = 475.f, sensitivity = 292.f * fovmodifier;
const int aimingintank = EMU_ReadInt(GE_tankflag) == 1 && currentweapon == 32; // flag if player is driving tank with tank equipped as weapon
if(aimingflag) // if player is aiming
{
const float mouseaccel = PROFILE[player].SETTINGS[ACCELERATION] ? sqrt(DEVICE[player].XPOS * DEVICE[player].XPOS + DEVICE[player].YPOS * DEVICE[player].YPOS) / TICKRATE / 12.0f * PROFILE[player].SETTINGS[ACCELERATION] : 0;
crosshairposx[player] += DEVICE[player].XPOS / 10.0f * (PROFILE[player].SETTINGS[SENSITIVITY] / sensitivity / RATIOFACTOR) * fmax(mouseaccel, 1); // calculate the crosshair position
crosshairposy[player] += (!PROFILE[player].SETTINGS[INVERTPITCH] ? DEVICE[player].YPOS : -DEVICE[player].YPOS) / 10.0f * (PROFILE[player].SETTINGS[SENSITIVITY] / sensitivity) * fmax(mouseaccel, 1);
crosshairposx[player] = ClampFloat(crosshairposx[player], -CROSSHAIRLIMIT, CROSSHAIRLIMIT); // apply clamp then inject
crosshairposy[player] = ClampFloat(crosshairposy[player], -CROSSHAIRLIMIT, CROSSHAIRLIMIT);
if(aimingintank) // if player is aiming while driving tank with tank equipped as weapon, set x axis crosshair to 0 (like the original game - so you cannot aim across the screen because the tank barrel is locked in the center)
crosshairposx[player] = 0;
EMU_WriteFloat(playerbase[player] + GE_crosshairx, crosshairposx[player]);
EMU_WriteFloat(playerbase[player] + GE_crosshairy, crosshairposy[player]);
EMU_WriteFloat(playerbase[player] + GE_gunx, crosshairposx[player] * RATIOFACTOR * (1.11f + (currentweapon >= 0 && currentweapon <= 32 ? offsetpos[0][currentweapon] : 0.15f) * 1.5f) + fovratio - 1); // calculate and inject the gun angles (uses pre-made pos table or if unknown weapon use fail-safe value)
EMU_WriteFloat(playerbase[player] + GE_guny, crosshairposy[player] * (1.11f + (currentweapon >= 0 && currentweapon <= 32 ? offsetpos[1][currentweapon] : 0) * 1.5f) + fovratio - 1);
if(crosshairx > 0 && crosshairx / CROSSHAIRLIMIT > threshold) // if crosshair is within threshold of the border then calculate a linear scrolling speed and enable mouselook
aimx[player] = (crosshairx / CROSSHAIRLIMIT - threshold) * speed * TIMESTEP;
else if(crosshairx < 0 && crosshairx / CROSSHAIRLIMIT < -threshold)
aimx[player] = (crosshairx / CROSSHAIRLIMIT + threshold) * speed * TIMESTEP;
else
aimx[player] = 0;
if(crosshairy > 0 && crosshairy / CROSSHAIRLIMIT > threshold)
aimy[player] = (crosshairy / CROSSHAIRLIMIT - threshold) * speed * TIMESTEP;
else if(crosshairy < 0 && crosshairy / CROSSHAIRLIMIT < -threshold)
aimy[player] = (crosshairy / CROSSHAIRLIMIT + threshold) * speed * TIMESTEP;
else
aimy[player] = 0;
}
else // player is not aiming so reset crosshairposxy values
crosshairposx[player] = crosshairx, crosshairposy[player] = crosshairy;
}
//==========================================================================
// Purpose: calculate and send emulator key combo
//==========================================================================
static void GE_Controller(void)
{
for(int player = PLAYER1; player < ALLPLAYERS; player++)
{
CONTROLLER[player].U_CBUTTON = DEVICE[player].BUTTONPRIM[FORWARDS] || DEVICE[player].BUTTONSEC[FORWARDS];
CONTROLLER[player].D_CBUTTON = DEVICE[player].BUTTONPRIM[BACKWARDS] || DEVICE[player].BUTTONSEC[BACKWARDS];
CONTROLLER[player].L_CBUTTON = DEVICE[player].BUTTONPRIM[STRAFELEFT] || DEVICE[player].BUTTONSEC[STRAFELEFT];
CONTROLLER[player].R_CBUTTON = DEVICE[player].BUTTONPRIM[STRAFERIGHT] || DEVICE[player].BUTTONSEC[STRAFERIGHT];
CONTROLLER[player].Z_TRIG = DEVICE[player].BUTTONPRIM[FIRE] || DEVICE[player].BUTTONSEC[FIRE] || DEVICE[player].BUTTONPRIM[PREVIOUSWEAPON] || DEVICE[player].BUTTONSEC[PREVIOUSWEAPON];
CONTROLLER[player].R_TRIG = DEVICE[player].BUTTONPRIM[AIM] || DEVICE[player].BUTTONSEC[AIM];
#ifndef SPEEDRUN_BUILD // speedrun build does not have reload button support
CONTROLLER[player].RELOAD_HACK = DEVICE[player].BUTTONPRIM[RELOAD] || DEVICE[player].BUTTONSEC[RELOAD];
#endif
CONTROLLER[player].A_BUTTON = DEVICE[player].BUTTONPRIM[ACCEPT] || DEVICE[player].BUTTONSEC[ACCEPT] || DEVICE[player].BUTTONPRIM[PREVIOUSWEAPON] || DEVICE[player].BUTTONSEC[PREVIOUSWEAPON] || DEVICE[player].BUTTONPRIM[NEXTWEAPON] || DEVICE[player].BUTTONSEC[NEXTWEAPON];
CONTROLLER[player].B_BUTTON = DEVICE[player].BUTTONPRIM[CANCEL] || DEVICE[player].BUTTONSEC[CANCEL];
CONTROLLER[player].START_BUTTON = DEVICE[player].BUTTONPRIM[START] || DEVICE[player].BUTTONSEC[START];
DEVICE[player].ARROW[0] = (DEVICE[player].BUTTONPRIM[UP] || DEVICE[player].BUTTONSEC[UP]) ? 127 : 0;
DEVICE[player].ARROW[1] = (DEVICE[player].BUTTONPRIM[DOWN] || DEVICE[player].BUTTONSEC[DOWN]) ? (EMU_ReadInt(GE_menupage) != 11 ? -127 : -128) : 0; // clamp to -127 for menus due to overflow bug
DEVICE[player].ARROW[2] = (DEVICE[player].BUTTONPRIM[LEFT] || DEVICE[player].BUTTONSEC[LEFT]) ? -128 : 0;
DEVICE[player].ARROW[3] = (DEVICE[player].BUTTONPRIM[RIGHT] || DEVICE[player].BUTTONSEC[RIGHT]) ? 127 : 0;
CONTROLLER[player].X_AXIS = DEVICE[player].ARROW[0] + DEVICE[player].ARROW[1];
CONTROLLER[player].Y_AXIS = DEVICE[player].ARROW[2] + DEVICE[player].ARROW[3];
}
if(EMU_ReadInt(GE_menupage) != 11 && !CONTROLLER[PLAYER1].B_BUTTON) // pressing aim will act like the back button (only in menus and for player 1)
CONTROLLER[PLAYER1].B_BUTTON = DEVICE[PLAYER1].BUTTONPRIM[AIM] || DEVICE[PLAYER1].BUTTONSEC[AIM];
}
//==========================================================================
// Purpose: inject hacks into rom before code has been cached
//==========================================================================
static void GE_InjectHacks(void)
{
const int addressarray[27] = {0x000B7EA0, 0x000B7EB8, 0x0009C7F8, 0x0009C7FC, 0x0009C80C, 0x0009C810, 0x0009C998, 0x0009C99C, 0x0009C9AC, 0x0009C9B0, 0x000AE4DC, 0x000AE4E0, 0x000AE4E4, 0x000AE4E8, 0x000AE4EC, 0x000AE4F0, 0x000AE4F4, 0x000AE4F8, 0x000AE4FC, 0x000AE500, 0x000AE504, 0x000AE508, 0x000AE50C, 0x000AE510, 0x000AE514, 0x000AE518, 0x000AE51C}, codearray[27] = {0x00000000, 0x00000000, 0x0BC1E66B, 0x460C5100, 0x0BC1E66F, 0x460E3280, 0x0BC1E673, 0x460C4100, 0x0BC1E677, 0x460E5200, 0x8C590124, 0x53200001, 0xE4440FF0, 0x0BC19F34, 0x8C590124, 0x53200001, 0xE44A0FF4, 0x0BC19F39, 0x8C590124, 0x53200001, 0xE4441004, 0x0BC19F9C, 0x8C590124, 0x53200001, 0xE4481008, 0x0BC19FA1, 0x00000000}; // disable autostand code, add branch to crosshair code so cursor aiming mode is absolute (without jitter)
for(int index = 0; index < 27; index++) // inject code array
EMU_WriteROM(addressarray[index], codearray[index]);
#ifndef SPEEDRUN_BUILD // gives unfair advantage, remove for speedrun build
const int reloadhack_address[23] = {0x000B7754, 0x000B6EC0, 0x000B7508, 0x000B750C, 0x000B7510, 0x000B7514, 0x000B7518, 0x000B751C, 0x000B7520, 0x000BEA68, 0x000BEA6C, 0x000BEA74, 0x000F30FC, 0x000F3100, 0x000F3104, 0x000F3108, 0x000F310C, 0x000F3110, 0x000F3114, 0x000F3118, 0x000F311C, 0x000F3120, 0x000F3124}, reloadhack_code[23] = {0x8FAB01C8, 0x304F4040, 0x330D4000, 0x51A00091, 0x8E0D0000, 0x3C028003, 0x8C4D6448, 0x11A0002D, 0x8C4C6450, 0x8C4200D0, 0x304B0040, 0x304A4000, 0x8E020000, 0x51600005, 0x00000000, 0x0FC17659, 0x00002025, 0x0FC17659, 0x24040001, 0x11400003, 0x00000000, 0x0FC0F13C, 0x00000000}; // add reload button hack
for(int index = 0; index < 23; index++) // inject code array
EMU_WriteROM(reloadhack_address[index], reloadhack_code[index]);
if((unsigned int)EMU_ReadROM(GE_controlstyle) == 0x8DC22A58) // if safe to overwrite
EMU_WriteROM(GE_controlstyle, 0x34020001); // always force game to use 1.2 control style
if((unsigned int)EMU_ReadROM(GE_reversepitch) == 0x8C420A84) // if safe to overwrite
EMU_WriteROM(GE_reversepitch, 0x34020001); // always force game to use upright pitch
if((unsigned int)EMU_ReadInt(GE_pickupyaxisthreshold) == 0xBF490FDB && EMU_ReadInt(GE_menupage) == 0) // if safe to overwrite
EMU_WriteFloat(GE_pickupyaxisthreshold, -60.f * PI / 180.f); // overwrite default y axis limit for picking up items (from -45 to -60)
if(OVERRIDEFOV != 60) // override default fov
{
float newfov = OVERRIDEFOV;
unsigned int unsignedinteger = *(unsigned int *)(float *)(&newfov);
EMU_WriteROM(GE_defaultfov, 0x3C010000 + (short)(unsignedinteger / 0x10000));
EMU_WriteROM(GE_defaultfovinit, 0x3C010000 + (short)(unsignedinteger / 0x10000));
EMU_WriteROM(GE_defaultfovzoom, 0x3C010000 + (short)(unsignedinteger / 0x10000));
if(!bypassviewmodelfovtweak) // allow user to bypass viewmodel position compensation for override fov (so they can see more detail at the expense of introducing draw order glitches)
{
if(EMU_ReadInt(GE_weaponypos) == 0 && EMU_ReadInt(GE_weaponzpos) == 0) // if first weapon slot position is default
{
for(int index = 0; index <= 32; index++) // cycle through first 32 weapons
{
const float fovoffset = OVERRIDEFOV - 60;
const float weaponypos = EMU_ReadFloat(GE_weaponypos + (index * 0x70)) - (fovoffset / (2.25f * 4.f)); // adjust weapon Y/Z positions for override field of view
const float weaponzpos = EMU_ReadFloat(GE_weaponzpos + (index * 0x70)) + (fovoffset / 2.75f);
EMU_WriteFloat(GE_weaponypos + (index * 0x70), weaponypos);
EMU_WriteFloat(GE_weaponzpos + (index * 0x70), weaponzpos);
}
}
}
if(OVERRIDEFOV > 60)
EMU_WriteFloat(GE_defaultzoomspeed, (OVERRIDEFOV - 60) * ((1.7f - 0.909091f) / 60.0f) + 0.909091f); // adjust zoom speed default (0.909091 default, 1.7 max)
}
if((unsigned int)EMU_ReadInt(GE_defaultratio) == 0x3FE38E39 && (overrideratiowidth != 16 || overrideratioheight != 9)) // override default 16:9 ratio
{
EMU_WriteFloat(GE_defaultratio, (float)overrideratiowidth / (float)overrideratioheight); // apply new ratio
float newratio = (4.f / 3.f) / ((float)overrideratiowidth / (float)overrideratioheight); // now apply ratio factor to crosshair scale
unsigned int unsignedinteger = *(unsigned int *)(float *)(&newratio);
EMU_WriteROM(GE_defaultratiocrosshair, 0x3C010000 + (short)(unsignedinteger / 0x10000));
}
#endif
if(geshowcrosshair) // inject show crosshair hack
{
EMU_WriteROM(GE_showcrosshair, 0x8C4E01C8); // replace lw $t6, 0x1128 ($v0) (8C4E1128) with lw $t6, 0x01C8 ($v0) (8C4E01C8)
if(EMU_ReadROM(GE_crosshairimage) == 0x000008BC && EMU_ReadROM(0x28) != 0x45522020) // if crosshair image found and rom isn't Goldfinger 64 (why? because GF64 replaced beta crosshair image with ammo icon)
EMU_WriteROM(GE_crosshairimage, 0x000008BD); // replace crosshair image with beta crosshair
}
if(CONTROLLER[PLAYER1].Z_TRIG && CONTROLLER[PLAYER1].R_TRIG) // skip intros if holding down fire + aim
{
EMU_WriteInt(GE_introcounter, 0x00001000);
EMU_WriteInt(GE_seenintroflag, 0);
}
}
//==========================================================================
// Purpose: run when emulator closes rom
// Changes Globals: playerbase, safetocrouch, safetostand, crouchstance
//==========================================================================
void GE_Quit(void)
{
for(int player = PLAYER1; player < ALLPLAYERS; player++)
{
playerbase[player] = 0;
GE_ResetCrouchToggle(player);
}
}
-101
View File
@@ -1,101 +0,0 @@
//==========================================================================
// Mouse Injector Plugin
//==========================================================================
// Copyright (C) 2016-2021 Carnivorous
// All rights reserved.
//
// Mouse Injector is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, visit http://www.gnu.org/licenses/gpl-2.0.html
//==========================================================================
#define LOAD_SHALF_PARAM(param) *(short *) ((unsigned char *)rdramptr[(((param) >> 12))] + (((param) & 0x00000FFF) ^ 2))
#define LOAD_SWORD_PARAM(param) *(int *)((unsigned char *)rdramptr[(((param) >> 12))] + (((param) & 0x00000FFF)))
#define LOAD_UWORD_PARAM(param) *(unsigned int *)((unsigned char *)rdramptr[(((param) >> 12))] + (((param) & 0x00000FFF)))
#define WITHINRANGE(param) ((rdramptr != 0) && ((param & 0xFF800000U) == 0x80000000U))
#define GARBAGESHORT (short)0xABAD
#define GARBAGEINT (int)0xABADC0DE
//==========================================================================
// Purpose: read short from memory
// Parameter: address
//==========================================================================
static inline short EMU_ReadShort(const unsigned int addr)
{
if(WITHINRANGE(addr))
return LOAD_SHALF_PARAM(addr);
return GARBAGESHORT;
}
//==========================================================================
// Purpose: write short to memory location
// Parameter: address, value
//==========================================================================
static inline void EMU_WriteShort(const unsigned int addr, const short value)
{
if(WITHINRANGE(addr))
LOAD_SHALF_PARAM(addr) = value;
}
//==========================================================================
// Purpose: read int from memory
// Parameter: address
//==========================================================================
static inline int EMU_ReadInt(const unsigned int addr)
{
if(WITHINRANGE(addr))
return LOAD_SWORD_PARAM(addr);
return GARBAGEINT;
}
//==========================================================================
// Purpose: write int to memory location
// Parameter: address, value
//==========================================================================
static inline void EMU_WriteInt(const unsigned int addr, const int value)
{
if(WITHINRANGE(addr))
LOAD_SWORD_PARAM(addr) = value;
}
//==========================================================================
// Purpose: read float from memory
// Parameter: address
//==========================================================================
static inline float EMU_ReadFloat(const unsigned int addr)
{
if(WITHINRANGE(addr))
return *((float *)&LOAD_UWORD_PARAM(addr));
return GARBAGEINT;
}
//==========================================================================
// Purpose: write float to memory location
// Parameter: address, value
//==========================================================================
static inline void EMU_WriteFloat(const unsigned int addr, const float value)
{
if(WITHINRANGE(addr))
LOAD_UWORD_PARAM(addr) = *(unsigned int *)(&value);
}
//==========================================================================
// Purpose: read int from emulator's copy of rom
// Parameter: address
//==========================================================================
static inline unsigned EMU_ReadROM(const unsigned int addr)
{
return (unsigned)romptr[addr / 0x4];
}
//==========================================================================
// Purpose: write to emulator's copy of rom
// Parameter: address, value
//==========================================================================
static inline void EMU_WriteROM(const unsigned int addr, const unsigned int value)
{
if(romptr != 0)
romptr[addr / 0x4] = (void *)value;
}
@@ -1,555 +0,0 @@
//==========================================================================
// Mouse Injector Plugin
//==========================================================================
// Copyright (C) 2016-2021 Carnivorous
// All rights reserved.
//
// Mouse Injector is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, visit http://www.gnu.org/licenses/gpl-2.0.html
//==========================================================================
#include <math.h>
#include "../global.h"
#include "../maindll.h"
#include "game.h"
#include "memory.h"
#define GUNAIMLIMIT 14.12940025 // 0x41621206
#define CROSSHAIRLIMIT 18.76135635 // 0x41961742
#define GUNRECOILXLIMIT 756.1247559 // 0x443D07FC
#define GUNRECOILYLIMIT 57.63883972 // 0x42668E2C
#define BIKEXROTATIONLIMIT 6.282184601 // 0x40C907A8
#define BIKEROLLLIMIT 0.7852724195 // 0xBF49079D/0x3F49079D
#define PI 3.1415927 // 0x40490FDB
// PERFECT DARK ADDRESSES - OFFSET ADDRESSES BELOW (REQUIRES PLAYERBASE/BIKEBASE TO USE)
#define PD_stanceflag 0x801BB74C - 0x801BB6A0
#define PD_deathflag 0x801BB778 - 0x801BB6A0
#define PD_camx 0x801BB7E4 - 0x801BB6A0
#define PD_camy 0x801BB7F4 - 0x801BB6A0
#define PD_fov 0x801BCEE8 - 0x801BB6A0
#define PD_crosshairx 0x801BCD08 - 0x801BB6A0
#define PD_crosshairy 0x801BCD0C - 0x801BB6A0
#define PD_grabflag 0x801BB850 - 0x801BB6A0
#define PD_bikeptr 0x801BD10C - 0x801BB6A0
#define PD_thirdperson 0x801BB6A0 - 0x801BB6A0
#define PD_gunrx 0x801BC374 - 0x801BB6A0
#define PD_gunry 0x801BC378 - 0x801BB6A0
#define PD_gunlx 0x801BCB18 - 0x801BB6A0
#define PD_gunly 0x801BCB1C - 0x801BB6A0
#define PD_aimingflag 0x801BB7C0 - 0x801BB6A0
#define PD_gunrstate 0x801BC2DC - 0x801BB6A0
#define PD_gunlstate 0x801BCA80 - 0x801BB6A0
#define PD_gunrxrecoil 0x801BBE98 - 0x801BB6A0
#define PD_gunryrecoil 0x801BBE9C - 0x801BB6A0
#define PD_gunlxrecoil 0x801BC63C - 0x801BB6A0
#define PD_gunlyrecoil 0x801BC640 - 0x801BB6A0
#define PD_currentweapon 0x801BCC28 - 0x801BB6A0
#define PD_bikebase 0x805142C4 - 0x805142C0
#define PD_bikeyaw 0x804B1AB4 - 0x804B1A48
#define PD_bikeroll 0x804B1B04 - 0x804B1A48
#define PD_camspybase 0x801BBB20 - 0x801BB6A0
#define PD_camspyflag 0x801BB6D4 - 0x801BB6A0
#define PD_camspyx 0x80607EEC - 0x80607ED0
#define PD_camspyy 0x80607EF8 - 0x80607ED0
#define PD_camspyycos 0x80607EFC - 0x80607ED0
#define PD_camspyysin 0x80607F00 - 0x80607ED0
// STATIC ADDRESSES BELOW
#define JOANNADATA(X) (unsigned int)EMU_ReadInt(0x8009A024 + (X * 0x4)) // player pointer address (0x4 offset for each players)
#define PD_menu(X) 0x80070750 + (X * 0x4) // player menu flag (0 = PD is in menu) (0x4 offset for each players)
#define PD_camera 0x8009A26C // camera flag (1 = gameplay, 2 & 3 = ???, 4 = multiplayer sweep, 5 = gameover screen, 6 = cutscene mode, 7 = force player to move: extraction's dark room)
#define PD_pause 0x80084014 // menu flag (1 = PD is paused)
#define PD_stageid 0x800624E4 // stage id
#define PD_debugtext 0x803C79F0 // debug text (used to check if PD is running)
#define PD_mppause 0x800ACBA6 // used to check if multiplayer match is paused
#define PD_defaultratio 0x803CD680 // 16:9 ratio default
#define PD_defaultfov 0x802EAA5C // field of view default
#define PD_defaultfovzoom 0x802EACFC // field of view default for zoom
#define PD_defaultzoominspeed 0x802DA8F8 // default zoom in speed
#define PD_defaultzoomoutspeed 0x802DA924 // default zoom out speed
#define PD_introcounter 0x800624C4 // counter for intro
#define PD_controlstyle 0x80372728 // instruction reads the current controller style
#define PD_reversepitch 0x803727A0 // instruction reads the current reverse pitch option
#define PD_pickupyaxisthreshold 0x803CAE78 // y axis threshold on picking up weapons
#define PD_weapontable 0x8006FF1C // weapon pointer table, used to change view model positions
#define PD_radialmenutimer 0x802EA2BC // time instruction for radial menu to appear (15 ticks)
#define PD_radialmenualphainit 0x803D2CDC // initial alpha value for all menus
#define PD_blurfix 0x802DB68C // nop gap on chr function to store our blur fix
#define PD_hiresoption 0x80322D9C // argument used to set hires mode on within options
#define PD_camspylookspringup 0x802F13E8 // save instruction for adjusted camspy look spring pitch
#define PD_camspylookspringdown 0x802F143C // save instruction for adjusted camspy look spring pitch
static unsigned int playerbase[4] = {0}; // current player's joannadata address
static int xstick[4] = {0}, ystick[4] = {0}, usingstick[4] = {0}, slayerairbrakes[4] = {0}; // for camspy/slayer controls
static float xmenu[4] = {0}, ymenu[4] = {0}; // for pd radial nav function
static int radialmenudirection[4][4] = {{0}, {0}, {0}, {0}}; // used to override c buttons if user is interacting with a radial menu
static int safetocrouch[4] = {1, 1, 1, 1}, safetostand[4] = {0}, crouchstance[4] = {2, 2, 2, 2}; // used for crouch toggle (limits tick-tocking)
static int safetolowercamspy[4] = {0}, safetoraisecamspy[4] = {1, 1, 1, 1}, camspystance[4] = {1, 1, 1, 1}; // used for lowering/raising camspy height
static float crosshairposx[4], crosshairposy[4], aimx[4], aimy[4];
static int gunrcenter[4], gunlcenter[4];
int PD_Status(void);
void PD_Inject(void);
static void PD_Crouch(const int player);
#define PD_ResetCrouchToggle(X) safetocrouch[X] = 1, safetostand[X] = 0, crouchstance[X] = 2 // reset crouch toggle bind
#define PD_ResetCamspyStance(X) safetolowercamspy[X] = 0, safetoraisecamspy[X] = 1, camspystance[X] = 1 // reset camspy stance
#define PD_ResetCamspySlayerStick(X) xstick[X] = 0, ystick[X] = 0, usingstick[X] = 0, slayerairbrakes[X] = 0 // reset x/y stick array for camspy/slayer
#define PD_ResetRadialMenuBtns(X) for(int direction = 0; direction < 4; direction++) radialmenudirection[X][direction] = 0 // reset direction buttons
static void PD_AimMode(const int player, const int aimingflag, const float fov, const float basefov);
static void PD_CamspySlayer(const int player, const int camspyflag, const float sensitivity);
static void PD_RadialMenuNav(const int player);
static void PD_Controller(void);
static void PD_InjectHacks(void);
void PD_Quit(void);
static const GAMEDRIVER GAMEDRIVER_INTERFACE =
{
"Perfect Dark",
PD_Status,
PD_Inject,
PD_Quit
};
const GAMEDRIVER *GAME_PERFECTDARK = &GAMEDRIVER_INTERFACE;
//==========================================================================
// Purpose: returns a value, which is then used to check what game is running in game.c
// Q: What is happening here?
// A: We look up some static addresses and if the values are within the expected ranges the program can assume that the game is currently running
//==========================================================================
int PD_Status(void)
{
const int pd_menu = EMU_ReadInt(PD_menu(PLAYER1)), pd_camera = EMU_ReadInt(PD_camera), pd_pause = EMU_ReadInt(PD_pause), pd_romcheck = EMU_ReadInt(PD_debugtext);
return (pd_menu >= 0 && pd_menu <= 1 && pd_camera >= 0 && pd_camera <= 7 && pd_pause >= 0 && pd_pause <= 1 && pd_romcheck == 0x206F6620); // if Perfect Dark is current game
}
//==========================================================================
// Purpose: calculate mouse movement and inject into current game
// Changes Globals: safetocrouch, safetostand, crouchstance
//==========================================================================
void PD_Inject(void)
{
if(EMU_ReadInt(PD_stageid) < 1) // hacks can only be injected at boot sequence before code blocks are cached, so inject until player has spawned
PD_InjectHacks();
const int camera = EMU_ReadInt(PD_camera);
const int pause = EMU_ReadInt(PD_pause);
const int mppause = (EMU_ReadShort(PD_mppause) & 0xFF00);
for(int player = PLAYER1; player < ALLPLAYERS; player++)
{
if(PROFILE[player].SETTINGS[CONFIG] == DISABLED) // bypass disabled players
continue;
playerbase[player] = JOANNADATA(player);
const int dead = EMU_ReadInt(playerbase[player] + PD_deathflag);
const int menu = EMU_ReadInt(PD_menu(player));
const int aimingflag = EMU_ReadInt(playerbase[player] + PD_aimingflag);
const int grabflag = EMU_ReadInt(playerbase[player] + PD_grabflag);
const unsigned int bikebase = EMU_ReadInt((unsigned int)EMU_ReadInt(playerbase[player] + PD_bikeptr) + PD_bikebase);
const int thirdperson = EMU_ReadInt(playerbase[player] + PD_thirdperson);
const int cursoraimingflag = PROFILE[player].SETTINGS[PDAIMMODE] && aimingflag && EMU_ReadInt(playerbase[player] + PD_currentweapon) != 50; // don't use cursoraiming when using the horizon scanner
const float fov = EMU_ReadFloat(playerbase[player] + PD_fov);
const float basefov = fov > 60.0f ? (float)OVERRIDEFOV : 60.0f;
const float mouseaccel = PROFILE[player].SETTINGS[ACCELERATION] ? sqrt(DEVICE[player].XPOS * DEVICE[player].XPOS + DEVICE[player].YPOS * DEVICE[player].YPOS) / TICKRATE / 12.0f * PROFILE[player].SETTINGS[ACCELERATION] : 0;
const float sensitivity = PROFILE[player].SETTINGS[SENSITIVITY] / 40.0f * fmax(mouseaccel, 1);
const float gunsensitivity = sensitivity * (PROFILE[player].SETTINGS[CROSSHAIR] / 2.5f);
float camx = EMU_ReadFloat(playerbase[player] + PD_camx), camy = EMU_ReadFloat(playerbase[player] + PD_camy);
if(camx >= 0 && camx <= 360 && camy >= -90 && camy <= 90 && fov >= 1 && fov <= FOV_MAX && dead == 0 && menu == 1 && pause == 0 && mppause == 0 && camera == 1 && (grabflag == 0 || grabflag == 4 || grabflag == 3)) // if safe to inject
{
if(thirdperson == 1 || thirdperson == 2) // if player is using the slayer/camspy, memory inject camspy/translate mouse input to analog stick and continue to next player
{
PD_CamspySlayer(player, thirdperson == 2, sensitivity);
continue;
}
PD_AimMode(player, cursoraimingflag, fov, basefov);
if(grabflag != 3) // if player is on foot
{
PD_Crouch(player);
if(!cursoraimingflag) // if not aiming (or pdaimmode is off)
camx += DEVICE[player].XPOS / 10.0f * sensitivity * (fov / basefov); // regular mouselook calculation
else
camx += aimx[player] * (fov / basefov); // scroll screen with aimx/aimy
while(camx < 0)
camx += 360;
while(camx >= 360)
camx -= 360;
EMU_WriteFloat(playerbase[player] + PD_camx, camx);
}
else if(WITHINRANGE(bikebase)) // if player is riding hoverbike (and hoverbike address is legal)
{
PD_ResetCrouchToggle(player);
float bikeyaw = EMU_ReadFloat(bikebase + PD_bikeyaw), bikeroll = EMU_ReadFloat(bikebase + PD_bikeroll);
if(!cursoraimingflag)
{
bikeyaw -= DEVICE[player].XPOS / 10.0f * sensitivity / (360 / BIKEXROTATIONLIMIT) * (fov / basefov);
bikeroll += DEVICE[player].XPOS / 10.0f * sensitivity * (fov / basefov) / 100;
}
else
{
bikeyaw -= aimx[player] / (360 / BIKEXROTATIONLIMIT) * (fov / basefov);
bikeroll += aimx[player] * sensitivity * (fov / basefov) / 100;
}
while(bikeyaw < 0)
bikeyaw += BIKEXROTATIONLIMIT;
while(bikeyaw >= BIKEXROTATIONLIMIT)
bikeyaw -= BIKEXROTATIONLIMIT;
bikeroll = ClampFloat(bikeroll, -BIKEROLLLIMIT, BIKEROLLLIMIT);
EMU_WriteFloat(bikebase + PD_bikeyaw, bikeyaw);
EMU_WriteFloat(bikebase + PD_bikeroll, bikeroll);
}
if(!cursoraimingflag)
camy += (!PROFILE[player].SETTINGS[INVERTPITCH] ? -DEVICE[player].YPOS : DEVICE[player].YPOS) / 10.0f * sensitivity * (fov / basefov);
else
camy += -aimy[player] * (fov / basefov);
camy = ClampFloat(camy, -90, 90);
EMU_WriteFloat(playerbase[player] + PD_camy, camy);
if(PROFILE[player].SETTINGS[CROSSHAIR] && !cursoraimingflag) // if crosshair movement is enabled and player isn't aiming (don't calculate weapon movement while the player is in aim mode)
{
float gunx = EMU_ReadFloat(playerbase[player] + PD_gunrx), crosshairx = EMU_ReadFloat(playerbase[player] + PD_crosshairx); // after camera x and y have been calculated and injected, calculate the gun/reload/crosshair movement
gunx += DEVICE[player].XPOS / (!aimingflag ? 10.0f : 40.0f) * gunsensitivity * (fov / basefov) * 0.05f / RATIOFACTOR;
crosshairx += DEVICE[player].XPOS / (!aimingflag ? 10.0f : 40.0f) * gunsensitivity * (fov / 4 / (basefov / 4)) * 0.05f / RATIOFACTOR;
if(aimingflag) // emulate cursor moving back to the center
gunx /= emuoverclock ? 1.03f : 1.07f, crosshairx /= emuoverclock ? 1.03f : 1.07f;
gunx = ClampFloat(gunx, -GUNAIMLIMIT, GUNAIMLIMIT);
crosshairx = ClampFloat(crosshairx, -CROSSHAIRLIMIT, CROSSHAIRLIMIT);
EMU_WriteFloat(playerbase[player] + PD_gunrx, gunx);
EMU_WriteFloat(playerbase[player] + PD_gunrxrecoil, crosshairx * (GUNRECOILXLIMIT / CROSSHAIRLIMIT));
EMU_WriteFloat(playerbase[player] + PD_gunlx, gunx);
EMU_WriteFloat(playerbase[player] + PD_gunlxrecoil, crosshairx * (GUNRECOILXLIMIT / CROSSHAIRLIMIT));
EMU_WriteFloat(playerbase[player] + PD_crosshairx, crosshairx);
if(camy > -90 && camy < 90) // only allow player's gun to pitch within a valid range
{
float guny = EMU_ReadFloat(playerbase[player] + PD_gunry), crosshairy = EMU_ReadFloat(playerbase[player] + PD_crosshairy);
guny += (!PROFILE[player].SETTINGS[INVERTPITCH] ? DEVICE[player].YPOS : -DEVICE[player].YPOS) / (!aimingflag ? 10.0f : 40.0f) * gunsensitivity * (fov / basefov) * 0.075f;
crosshairy += (!PROFILE[player].SETTINGS[INVERTPITCH] ? DEVICE[player].YPOS : -DEVICE[player].YPOS) / (!aimingflag ? 10.0f : 40.0f) * gunsensitivity * (fov / 4 / (basefov / 4)) * 0.1f;
if(aimingflag)
guny /= emuoverclock ? 1.15f : 1.35f, crosshairy /= emuoverclock ? 1.15f : 1.35f;
guny = ClampFloat(guny, -GUNAIMLIMIT, GUNAIMLIMIT);
crosshairy = ClampFloat(crosshairy, -CROSSHAIRLIMIT, CROSSHAIRLIMIT);
EMU_WriteFloat(playerbase[player] + PD_gunry, guny);
EMU_WriteFloat(playerbase[player] + PD_gunryrecoil, crosshairy * (GUNRECOILYLIMIT / CROSSHAIRLIMIT));
EMU_WriteFloat(playerbase[player] + PD_gunly, guny);
EMU_WriteFloat(playerbase[player] + PD_gunlyrecoil, crosshairy * (GUNRECOILYLIMIT / CROSSHAIRLIMIT));
EMU_WriteFloat(playerbase[player] + PD_crosshairy, crosshairy);
}
}
}
if(!dead && camera == 1 && !menu) // player is alive, in first person and is in menu
PD_RadialMenuNav(player); // check if player is in radial menu and translate mouse input to C buttons
else if(dead || camera != 1) // player is dead or not in first person camera
{
PD_ResetCrouchToggle(player); // reset crouch toggle
PD_ResetCamspyStance(player); // reset camspy stance
}
}
PD_Controller(); // set controller data
}
//==========================================================================
// Purpose: crouching function for Perfect Dark (2 = stand, 1 = kneel, 0 = duck)
// Changes Globals: safetocrouch, crouchstance, safetostand
//==========================================================================
static void PD_Crouch(const int player)
{
const int crouchheld = DEVICE[player].BUTTONPRIM[CROUCH] || DEVICE[player].BUTTONSEC[CROUCH];
const int kneelheld = DEVICE[player].BUTTONPRIM[KNEEL] || DEVICE[player].BUTTONSEC[KNEEL];
int stance = 2; // standing by default
if(crouchheld)
stance = 0;
else if(kneelheld)
stance = 1;
if(PROFILE[player].SETTINGS[CROUCHTOGGLE]) // check and toggle player stance
{
const int crouchkneelheld = crouchheld || kneelheld; // holding down crouch/kneel
if(safetocrouch[player] && crouchkneelheld) // stand to crouch/kneel
safetocrouch[player] = 0, crouchstance[player] = crouchheld ? 0 : 1;
else if(!safetocrouch[player] && !crouchkneelheld) // crouch/kneel is no longer being held, ready to stand
safetostand[player] = 1;
if(safetostand[player] && crouchkneelheld) // toggle to other stance
{
if(crouchheld && crouchstance[player] == 0 || kneelheld && crouchstance[player] == 1) // if pressed crouch/kneel twice, stand up
safetocrouch[player] = 1, crouchstance[player] = 2;
else
safetostand[player] = 0, crouchstance[player] = crouchheld ? 0 : 1; // switch to the other crouch stance (kneel/crouch)
}
else if(safetostand[player] && safetocrouch[player] && !crouchkneelheld) // crouch/kneel key not active, ready to toggle
safetostand[player] = 0;
stance = crouchstance[player];
}
EMU_WriteInt(playerbase[player] + PD_stanceflag, stance); // set in-game stance
}
//==========================================================================
// Purpose: replicate the original aiming system, uses aimx/y to move screen when crosshair is on border of screen
// Changes Globals: crosshairposx, crosshairposy, gunrcenter, gunlcenter, aimx, aimy
//==========================================================================
static void PD_AimMode(const int player, const int aimingflag, const float fov, const float basefov)
{
const float crosshairx = EMU_ReadFloat(playerbase[player] + PD_crosshairx), crosshairy = EMU_ReadFloat(playerbase[player] + PD_crosshairy);
const int gunrreload = EMU_ReadInt(playerbase[player] + PD_gunrstate) == 1, gunlreload = EMU_ReadInt(playerbase[player] + PD_gunlstate) == 1, unarmed = EMU_ReadInt(playerbase[player] + PD_currentweapon) < 2;
const float fovratio = fov / basefov, fovmodifier = basefov / 60.f; // basefov is 60 unless override is above 60
const float threshold = 0.72f, speed = 475.f, sensitivity = 100.f * fovmodifier, centertime = 60.f;
if(aimingflag) // if player is aiming
{
const float mouseaccel = PROFILE[player].SETTINGS[ACCELERATION] ? sqrt(DEVICE[player].XPOS * DEVICE[player].XPOS + DEVICE[player].YPOS * DEVICE[player].YPOS) / TICKRATE / 12.0f * PROFILE[player].SETTINGS[ACCELERATION] : 0;
crosshairposx[player] += DEVICE[player].XPOS / 10.0f * (PROFILE[player].SETTINGS[SENSITIVITY] / sensitivity / RATIOFACTOR) * fmax(mouseaccel, 1); // calculate the crosshair position
crosshairposy[player] += (!PROFILE[player].SETTINGS[INVERTPITCH] ? DEVICE[player].YPOS : -DEVICE[player].YPOS) / 10.0f * (PROFILE[player].SETTINGS[SENSITIVITY] / sensitivity) * fmax(mouseaccel, 1);
crosshairposx[player] = ClampFloat(crosshairposx[player], -CROSSHAIRLIMIT, CROSSHAIRLIMIT); // apply clamp then inject
crosshairposy[player] = ClampFloat(crosshairposy[player], -CROSSHAIRLIMIT, CROSSHAIRLIMIT);
EMU_WriteFloat(playerbase[player] + PD_crosshairx, crosshairposx[player]);
EMU_WriteFloat(playerbase[player] + PD_crosshairy, crosshairposy[player]);
if(unarmed || gunrreload) // if unarmed or reloading right weapon, remove from gunrcenter
gunrcenter[player] -= emuoverclock ? 1 : 2;
else if(gunrcenter[player] < (int)centertime) // increase gunrcenter over time until it equals centertime
gunrcenter[player] += emuoverclock ? 1 : 2;
if(gunlreload) // if reloading left weapon, remove from gunlcenter
gunlcenter[player] -= emuoverclock ? 1 : 2;
else if(gunlcenter[player] < (int)centertime)
gunlcenter[player] += emuoverclock ? 1 : 2;
if(gunrcenter[player] < 0)
gunrcenter[player] = 0;
if(gunlcenter[player] < 0)
gunlcenter[player] = 0;
EMU_WriteFloat(playerbase[player] + PD_gunrx, (gunrcenter[player] / centertime) * (crosshairposx[player] * 0.75f) + fovratio - 1); // calculate and inject the gun angles
EMU_WriteFloat(playerbase[player] + PD_gunrxrecoil, crosshairposx[player] * (GUNRECOILXLIMIT / CROSSHAIRLIMIT) * fovmodifier * RATIOFACTOR); // set the recoil to the correct rotation (if we don't, then the recoil is always z axis aligned)
EMU_WriteFloat(playerbase[player] + PD_gunry, (gunrcenter[player] / centertime) * (crosshairposy[player] * 0.66f) + fovratio - 1);
EMU_WriteFloat(playerbase[player] + PD_gunryrecoil, crosshairposy[player] * (GUNRECOILYLIMIT / CROSSHAIRLIMIT) * fovmodifier);
EMU_WriteFloat(playerbase[player] + PD_gunlx, (gunlcenter[player] / centertime) * (crosshairposx[player] * 0.75f) + fovratio - 1);
EMU_WriteFloat(playerbase[player] + PD_gunlxrecoil, crosshairposx[player] * (GUNRECOILXLIMIT / CROSSHAIRLIMIT) * fovmodifier * RATIOFACTOR);
EMU_WriteFloat(playerbase[player] + PD_gunly, (gunlcenter[player] / centertime) * (crosshairposy[player] * 0.66f) + fovratio - 1);
EMU_WriteFloat(playerbase[player] + PD_gunlyrecoil, crosshairposy[player] * (GUNRECOILYLIMIT / CROSSHAIRLIMIT) * fovmodifier);
if(crosshairx > 0 && crosshairx / CROSSHAIRLIMIT > threshold) // if crosshair is within threshold of the border then calculate a linear scrolling speed and enable mouselook
aimx[player] = (crosshairx / CROSSHAIRLIMIT - threshold) * speed * TIMESTEP;
else if(crosshairx < 0 && crosshairx / CROSSHAIRLIMIT < -threshold)
aimx[player] = (crosshairx / CROSSHAIRLIMIT + threshold) * speed * TIMESTEP;
else
aimx[player] = 0;
if(crosshairy > 0 && crosshairy / CROSSHAIRLIMIT > threshold)
aimy[player] = (crosshairy / CROSSHAIRLIMIT - threshold) * speed * TIMESTEP;
else if(crosshairy < 0 && crosshairy / CROSSHAIRLIMIT < -threshold)
aimy[player] = (crosshairy / CROSSHAIRLIMIT + threshold) * speed * TIMESTEP;
else
aimy[player] = 0;
}
else // player is not aiming so reset crosshairposxy and gunrlcenter
crosshairposx[player] = crosshairx, crosshairposy[player] = crosshairy, gunrcenter[player] = 0, gunlcenter[player] = 0;
}
//==========================================================================
// Purpose: handle camspy/slayer controlling
// Changes Globals: safetolowercamspy, camspystance, safetoraisecamspy, xstick, ystick, slayerairbrakes, usingstick
//==========================================================================
static void PD_CamspySlayer(const int player, const int camspyflag, const float sensitivity)
{
const int crouchheld = DEVICE[player].BUTTONPRIM[CROUCH] || DEVICE[player].BUTTONSEC[CROUCH] || DEVICE[player].BUTTONPRIM[KNEEL] || DEVICE[player].BUTTONSEC[KNEEL];
if(camspyflag)
{
const unsigned int camspybase = (unsigned int)EMU_ReadInt(playerbase[player] + PD_camspybase);
if(!WITHINRANGE(camspybase)) // if camspy pointer is invalid, abort
return;
const unsigned int camspyflag = (unsigned int)EMU_ReadInt(camspybase + PD_camspyflag) & 0x000000FF;
if(!camspyflag) // if camspy active flag is false, abort
return;
float camspyx = EMU_ReadFloat(camspybase + PD_camspyx), camspyy = EMU_ReadFloat(camspybase + PD_camspyy);
camspyx += DEVICE[player].XPOS / 10.0f * sensitivity; // regular mouselook calculation
while(camspyx < 0)
camspyx += 360;
while(camspyx >= 360)
camspyx -= 360;
EMU_WriteFloat(camspybase + PD_camspyx, camspyx);
if(camspyy > 90) // adjust minus range so clamping is easier to calculate
camspyy -= 360;
camspyy += (!PROFILE[player].SETTINGS[INVERTPITCH] ? -DEVICE[player].YPOS : DEVICE[player].YPOS) / 10.0f * (sensitivity / 1.5f); // slightly weaken y axis so camspy's fisheye effect isn't so sickening
#ifdef SPEEDRUN_BUILD // allow full 180 degrees for speedrun build
camspyy = ClampFloat(camspyy, -90, 90);
#else
camspyy = ClampFloat(camspyy, -75, 75); // limit range to usable field of view
#endif
if(camspyy < 0)
camspyy += 360;
EMU_WriteFloat(camspybase + PD_camspyy, camspyy);
const float camspyycos = cosf(camspyy * (1.f * PI / 180.f)), camspyysin = sinf(camspyy * (1.f * PI / 180.f)); // update view matrix angles (engine only does this when necessary - so we manually update it every tick)
EMU_WriteFloat(camspybase + PD_camspyycos, camspyycos);
EMU_WriteFloat(camspybase + PD_camspyysin, camspyysin);
if(safetolowercamspy[player] && crouchheld) // high to low
safetolowercamspy[player] = 0, camspystance[player] = 1;
else if(!safetolowercamspy[player] && !crouchheld) // crouch is no longer being held, ready to raise
safetoraisecamspy[player] = 1;
if(safetoraisecamspy[player] && crouchheld) // raise up
safetolowercamspy[player] = 1, camspystance[player] = 0;
else if(safetoraisecamspy[player] && safetolowercamspy[player] && !crouchheld) // crouch key not active, ready to toggle
safetoraisecamspy[player] = 0;
if(!DEVICE[player].BUTTONPRIM[AIM] && !DEVICE[player].BUTTONSEC[AIM]) // if not aiming, always adjust camspy height
xstick[player] = camspystance[player] ? 64 : -64;
else
xstick[player] = 0;
ystick[player] = 0;
}
else // slayer (does not use memory injection, otherwise handling would be too easy)
{
const float floatyness = 0.75f / TICKRATE;
xstick[player] = (int)((!PROFILE[player].SETTINGS[INVERTPITCH] ? DEVICE[player].YPOS : -DEVICE[player].YPOS) * sensitivity * 17.0f + (xstick[player] * floatyness));
ystick[player] = (int)((DEVICE[player].XPOS * sensitivity * 17.0f + (ystick[player] * floatyness)));
slayerairbrakes[player] = crouchheld || DEVICE[player].BUTTONPRIM[BACKWARDS] || DEVICE[player].BUTTONSEC[BACKWARDS];
}
xstick[player] = ClampInt(xstick[player], -128, 127);
ystick[player] = ClampInt(ystick[player], -128, 127);
usingstick[player] = 1;
}
//==========================================================================
// Purpose: translate mouse to weapon radial menu
// Changes Globals: xmenu, ymenu, radialmenudirection
//==========================================================================
static void PD_RadialMenuNav(const int player)
{
const float max = 19, threshold = 13, diagonalthres = 0.75;
if((DEVICE[player].BUTTONPRIM[ACCEPT] || DEVICE[player].BUTTONSEC[ACCEPT]) && !DEVICE[player].BUTTONPRIM[FIRE] && !DEVICE[player].BUTTONSEC[FIRE]) // if a button is held (reject if fire is pressed so aimx/y can be reset back to center)
{
xmenu[player] += DEVICE[player].XPOS / 10.0f * PROFILE[player].SETTINGS[SENSITIVITY] / 40.0f;
ymenu[player] += DEVICE[player].YPOS / 10.0f * PROFILE[player].SETTINGS[SENSITIVITY] / 40.0f;
xmenu[player] = ClampFloat(xmenu[player], -max, max);
ymenu[player] = ClampFloat(ymenu[player], -max, max);
if(ymenu[player] < -threshold) // c-up
radialmenudirection[player][FORWARDS] = 1;
else if(ymenu[player] > threshold) // c-down
radialmenudirection[player][BACKWARDS] = 1;
if(xmenu[player] < -threshold) // c-left
radialmenudirection[player][STRAFELEFT] = 1;
else if(xmenu[player] > threshold) // c-right
radialmenudirection[player][STRAFERIGHT] = 1;
if(xmenu[player] < -threshold && ymenu[player] < -threshold && (-xmenu[player] + -ymenu[player]) / (max * 2) > diagonalthres) // c-up-left
radialmenudirection[player][FORWARDS] = 1, radialmenudirection[player][STRAFELEFT] = 1;
else if(xmenu[player] > threshold && ymenu[player] < -threshold && (xmenu[player] + -ymenu[player]) / (max * 2) > diagonalthres) // c-up-right
radialmenudirection[player][FORWARDS] = 1, radialmenudirection[player][STRAFERIGHT] = 1;
else if(xmenu[player] < -threshold && ymenu[player] > threshold && (-xmenu[player] + ymenu[player]) / (max * 2) > diagonalthres) // c-down-left
radialmenudirection[player][BACKWARDS] = 1, radialmenudirection[player][STRAFELEFT] = 1;
else if(xmenu[player] > threshold && ymenu[player] > threshold && (xmenu[player] + ymenu[player]) / (max * 2) > diagonalthres) // c-down-right
radialmenudirection[player][BACKWARDS] = 1, radialmenudirection[player][STRAFERIGHT] = 1;
}
else
xmenu[player] = 0, ymenu[player] = 0;
}
//==========================================================================
// Purpose: calculate and send emulator key combo
// Changes Globals: xstick, ystick, usingstick, radialmenudirection
//==========================================================================
static void PD_Controller(void)
{
for(int player = PLAYER1; player < ALLPLAYERS; player++)
{
CONTROLLER[player].U_CBUTTON = DEVICE[player].BUTTONPRIM[FORWARDS] || DEVICE[player].BUTTONSEC[FORWARDS] || radialmenudirection[player][FORWARDS];
CONTROLLER[player].D_CBUTTON = DEVICE[player].BUTTONPRIM[BACKWARDS] || DEVICE[player].BUTTONSEC[BACKWARDS] || radialmenudirection[player][BACKWARDS];
CONTROLLER[player].L_CBUTTON = DEVICE[player].BUTTONPRIM[STRAFELEFT] || DEVICE[player].BUTTONSEC[STRAFELEFT] || radialmenudirection[player][STRAFELEFT];
CONTROLLER[player].R_CBUTTON = DEVICE[player].BUTTONPRIM[STRAFERIGHT] || DEVICE[player].BUTTONSEC[STRAFERIGHT] || radialmenudirection[player][STRAFERIGHT];
CONTROLLER[player].Z_TRIG = DEVICE[player].BUTTONPRIM[FIRE] || DEVICE[player].BUTTONSEC[FIRE] || DEVICE[player].BUTTONPRIM[PREVIOUSWEAPON] || DEVICE[player].BUTTONSEC[PREVIOUSWEAPON];
CONTROLLER[player].R_TRIG = DEVICE[player].BUTTONPRIM[AIM] || DEVICE[player].BUTTONSEC[AIM];
#ifndef SPEEDRUN_BUILD // speedrun build does not have reload button support
CONTROLLER[player].RELOAD_HACK = DEVICE[player].BUTTONPRIM[RELOAD] || DEVICE[player].BUTTONSEC[RELOAD];
#endif
CONTROLLER[player].A_BUTTON = DEVICE[player].BUTTONPRIM[ACCEPT] || DEVICE[player].BUTTONSEC[ACCEPT] || DEVICE[player].BUTTONPRIM[PREVIOUSWEAPON] || DEVICE[player].BUTTONSEC[PREVIOUSWEAPON] || DEVICE[player].BUTTONPRIM[NEXTWEAPON] || DEVICE[player].BUTTONSEC[NEXTWEAPON];
CONTROLLER[player].B_BUTTON = DEVICE[player].BUTTONPRIM[CANCEL] || DEVICE[player].BUTTONSEC[CANCEL];
CONTROLLER[player].START_BUTTON = DEVICE[player].BUTTONPRIM[START] || DEVICE[player].BUTTONSEC[START];
DEVICE[player].ARROW[0] = (DEVICE[player].BUTTONPRIM[UP] || DEVICE[player].BUTTONSEC[UP]) ? 127 : 0;
DEVICE[player].ARROW[1] = (DEVICE[player].BUTTONPRIM[DOWN] || DEVICE[player].BUTTONSEC[DOWN]) ? -128 : 0;
DEVICE[player].ARROW[2] = (DEVICE[player].BUTTONPRIM[LEFT] || DEVICE[player].BUTTONSEC[LEFT]) ? -128 : 0;
DEVICE[player].ARROW[3] = (DEVICE[player].BUTTONPRIM[RIGHT] || DEVICE[player].BUTTONSEC[RIGHT]) ? 127 : 0;
CONTROLLER[player].X_AXIS = DEVICE[player].ARROW[0] + DEVICE[player].ARROW[1];
CONTROLLER[player].Y_AXIS = DEVICE[player].ARROW[2] + DEVICE[player].ARROW[3];
if(usingstick[player]) // player is using camspy/slayer
{
if(xstick[player] != 0)
CONTROLLER[player].X_AXIS = xstick[player];
if(ystick[player] != 0)
CONTROLLER[player].Y_AXIS = ystick[player];
if(slayerairbrakes[player] != 0)
CONTROLLER[player].R_TRIG = slayerairbrakes[player];
usingstick[player] = 0;
}
else
PD_ResetCamspySlayerStick(player); // reset x/y stick
PD_ResetRadialMenuBtns(player); // reset radialmenudirection
}
}
//==========================================================================
// Purpose: inject hacks into rom before code has been cached
//==========================================================================
static void PD_InjectHacks(void)
{
const int addressarray[33] = {0x802C07B8, 0x802C07BC, 0x802C07EC, 0x802C07F0, 0x802C07FC, 0x802C0800, 0x802C0808, 0x802C0820, 0x802C0824, 0x802C082C, 0x802C0830, 0x803C7988, 0x803C798C, 0x803C7990, 0x803C7994, 0x803C7998, 0x803C799C, 0x803C79A0, 0x803C79A4, 0x803C79A8, 0x803C79AC, 0x803C79B0, 0x803C79B4, 0x803C79B8, 0x803C79BC, 0x803C79C0, 0x803C79C4, 0x803C79C8, 0x803C79CC, 0x803C79D0, 0x803C79D4, 0x803C79D8, 0x803C79DC}, codearray[33] = {0x0BC69E62, 0x8EA10120, 0x0BC69E67, 0x263107A4, 0x0BC69E6B, 0x4614C500, 0x46120682, 0x0BC69E6F, 0x26100004, 0x0BC69E73, 0x4614C500, 0x54200003, 0x00000000, 0xE6B21668, 0xE6A8166C, 0x0BC281F0, 0x8EA10120, 0x50200001, 0xE6380530, 0x0BC281FD, 0x8EA10120, 0x50200001, 0xE6340534, 0x0BC28201, 0x8EA10120, 0x50200001, 0xE6380530, 0x0BC2820A, 0x8EA10120, 0x50200001, 0xE6340534, 0x0BC2820D, 0x00000000}; // add branch to crosshair code so cursor aiming mode is absolute (without jitter)
for(int index = 0; index < 33; index++) // inject code array
EMU_WriteInt(addressarray[index], codearray[index]);
if((unsigned int)EMU_ReadInt(PD_camspylookspringup) == 0xE4640028) // add code to remove look spring logic for camspy
EMU_WriteInt(PD_camspylookspringup, 0x00000000); // replace instruction with nop
if((unsigned int)EMU_ReadInt(PD_camspylookspringdown) == 0xE4680028) // add code to remove look spring logic for camspy
EMU_WriteInt(PD_camspylookspringdown, 0x00000000); // replace instruction with nop
#ifndef SPEEDRUN_BUILD // gives unfair advantage, remove for speedrun build
const int reloadhack_address[22] = {0x8038A218, 0x8038A21C, 0x8038A228, 0x8038A22C, 0x8038A230, 0x8038A234, 0x8038A238, 0x8038A23C, 0x8038A240, 0x8038A244, 0x8038A248, 0x8038A24C, 0x8038A250, 0x8038A254, 0x8038A258, 0x8038A25C, 0x8038A268, 0x8038A270, 0x803C79E0, 0x803C79E4, 0x803C79E8, 0x803C79EC}, reloadhack_code[22] = {0x13000003, 0x00000000, 0x8E020480, 0x5440000B, 0x804C0037, 0x3C04800A, 0x8C84A24C, 0x0C005408, 0x34050040, 0x1040000B, 0x00000000, 0x0FC28886, 0x00002025, 0x0BC69E78, 0x00000000, 0x1180FFF5, 0x00000000, 0x34040001, 0x0FC28886, 0x34040001, 0x0BC5A89D, 0x00000000}; // add reload button hack
for(int index = 0; index < 22; index++) // inject code array
EMU_WriteInt(reloadhack_address[index], reloadhack_code[index]);
if((unsigned int)EMU_ReadInt(PD_controlstyle) == 0x9042C7FC) // if safe to overwrite
EMU_WriteInt(PD_controlstyle, 0x34020001); // always force game to use 1.2 control style
if((unsigned int)EMU_ReadInt(PD_reversepitch) == 0x000F102B) // if safe to overwrite
EMU_WriteInt(PD_reversepitch, 0x34020001); // always force game to use upright pitch
if((unsigned int)EMU_ReadInt(PD_pickupyaxisthreshold) == 0xBF4907A9) // if safe to overwrite
EMU_WriteFloat(PD_pickupyaxisthreshold, -60.f * PI / 180.f); // overwrite default y axis limit for picking up items (from -45 to -60)
if((unsigned int)EMU_ReadInt(PD_radialmenutimer) == 0x28410010 && emuoverclock) // make radial menu trigger quicker (from 15 to 8 ticks)
EMU_WriteInt(PD_radialmenutimer, 0x28410009);
if((unsigned int)EMU_ReadInt(PD_radialmenualphainit) == 0x3E99999A) // make radial menus initialize with 75% alpha
EMU_WriteFloat(PD_radialmenualphainit, 0.75f);
if((unsigned int)EMU_ReadInt(PD_blurfix) == 0x00000000) // add code to clear blur value on death
EMU_WriteInt(PD_blurfix, 0xA46002D8); // replace nop with sh $r0, 0x02D8 ($v1)
if((unsigned int)EMU_ReadInt(PD_hiresoption) == 0x24040001) // disable hires mode due (only benefits console/LLE plugins which are unsupported by 1964)
EMU_WriteInt(PD_hiresoption, 0x24040000); // always set to false
if(OVERRIDEFOV != 60) // override default fov
{
float newfov = OVERRIDEFOV;
unsigned int unsignedinteger = *(unsigned int *)(float *)(&newfov);
EMU_WriteInt(PD_defaultfov, 0x3C010000 + (short)(unsignedinteger / 0x10000));
EMU_WriteInt(PD_defaultfovzoom, 0x3C010000 + (short)(unsignedinteger / 0x10000));
if(!bypassviewmodelfovtweak) // allow user to bypass viewmodel position compensation for override fov (so they can see more detail at the expense of displaying animation culling keyframes)
{
if((unsigned int)EMU_ReadInt(EMU_ReadInt(PD_weapontable) + 0x30) == 0xC2240000) // if first weapon slot position is default
{
for(int index = 0; index < 64; index++) // cycle through first 64 weapons
{
const unsigned int weaponptr = EMU_ReadInt(PD_weapontable + (index * 4)); // get pointer for weapon slot
const float fovoffset = OVERRIDEFOV - 60;
const float weaponypos = EMU_ReadFloat(weaponptr + 0x30) - (fovoffset / (2.75f * 4.f)); // adjust weapon Y/Z positions for override field of view
const float weaponzpos = EMU_ReadFloat(weaponptr + 0x34) + (fovoffset / 3.f);
EMU_WriteFloat(weaponptr + 0x30, weaponypos);
EMU_WriteFloat(weaponptr + 0x34, weaponzpos);
}
}
}
if(OVERRIDEFOV > 60)
{
newfov = 15.f / (OVERRIDEFOV / 60.f);
unsignedinteger = *(unsigned int *)(float *)(&newfov);
EMU_WriteInt(PD_defaultzoominspeed, 0x3C010000 + (short)(unsignedinteger / 0x10000)); // adjust zoom in speed default (15.f)
newfov = 30.f * (OVERRIDEFOV / 60.f);
unsignedinteger = *(unsigned int *)(float *)(&newfov);
EMU_WriteInt(PD_defaultzoomoutspeed, 0x3C010000 + (short)(unsignedinteger / 0x10000)); // adjust zoom out speed default (30.f)
}
}
if((unsigned int)EMU_ReadInt(PD_defaultratio) == 0x3FAAAAAB && (overrideratiowidth != 16 || overrideratioheight != 9)) // override default 16:9 ratio
EMU_WriteFloat(PD_defaultratio, ((float)overrideratiowidth / (float)overrideratioheight) / (4.f / 3.f));
#endif
if(CONTROLLER[PLAYER1].Z_TRIG && CONTROLLER[PLAYER1].R_TRIG) // skip intros if holding down fire + aim
EMU_WriteInt(PD_introcounter, 0x00001000);
}
//==========================================================================
// Purpose: run when emulator closes rom
// Changes Globals: playerbase, safetocrouch, safetostand, crouchstance, xmenu, ymenu
//==========================================================================
void PD_Quit(void)
{
for(int player = PLAYER1; player < ALLPLAYERS; player++)
{
playerbase[player] = 0;
PD_ResetCrouchToggle(player);
PD_ResetCamspyStance(player);
xmenu[player] = 0, ymenu[player] = 0;
}
}
-130
View File
@@ -1,130 +0,0 @@
//==========================================================================
// Mouse Injector Plugin
//==========================================================================
// Copyright (C) 2016-2021 Carnivorous
// All rights reserved.
//
// Mouse Injector is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, visit http://www.gnu.org/licenses/gpl-2.0.html
//==========================================================================
#define __MOUSE_INJECTOR_VERSION__ "V2.3"
#define __CURRENTYEAR__ "2021"
#define CONSOLE { AllocConsole(); AttachConsole(GetCurrentProcessId()); freopen("CON", "w", stdout); }
#define ONLY1PLAYERACTIVE \
(PROFILE[PLAYER1].SETTINGS[CONFIG] != DISABLED && PROFILE[PLAYER2].SETTINGS[CONFIG] == DISABLED && PROFILE[PLAYER3].SETTINGS[CONFIG] == DISABLED && PROFILE[PLAYER4].SETTINGS[CONFIG] == DISABLED || \
PROFILE[PLAYER1].SETTINGS[CONFIG] == DISABLED && PROFILE[PLAYER2].SETTINGS[CONFIG] != DISABLED && PROFILE[PLAYER3].SETTINGS[CONFIG] == DISABLED && PROFILE[PLAYER4].SETTINGS[CONFIG] == DISABLED || \
PROFILE[PLAYER1].SETTINGS[CONFIG] == DISABLED && PROFILE[PLAYER2].SETTINGS[CONFIG] == DISABLED && PROFILE[PLAYER3].SETTINGS[CONFIG] != DISABLED && PROFILE[PLAYER4].SETTINGS[CONFIG] == DISABLED || \
PROFILE[PLAYER1].SETTINGS[CONFIG] == DISABLED && PROFILE[PLAYER2].SETTINGS[CONFIG] == DISABLED && PROFILE[PLAYER3].SETTINGS[CONFIG] == DISABLED && PROFILE[PLAYER4].SETTINGS[CONFIG] != DISABLED)
#if _MSC_VER && !__INTEL_COMPILER // here because some MSVC versions only support __inline :/
#define inline __inline
#endif
#define FOV_MIN 40
#define FOV_MAX 120
#define ARRAY_SIZE(array) ((size_t)(sizeof(array)/sizeof(*array)))
inline float ClampFloat(const float value, const float min, const float max)
{
const float test = value < min ? min : value;
return test > max ? max : test;
}
inline int ClampInt(const int value, const int min, const int max)
{
const int test = value < min ? min : value;
return test > max ? max : test;
}
// profile struct
enum CONTROLLERENUM {FORWARDS = 0, BACKWARDS, STRAFELEFT, STRAFERIGHT, FIRE, AIM, RELOAD, ACCEPT, CANCEL, START, CROUCH, KNEEL, PREVIOUSWEAPON, NEXTWEAPON, UP, DOWN, LEFT, RIGHT, TOTALBUTTONS};
enum CONFIGENUM {CONFIG = 0, SENSITIVITY, ACCELERATION, CROSSHAIR, INVERTPITCH, CROUCHTOGGLE, GEAIMMODE, PDAIMMODE, MOUSE, KEYBOARD, TOTALSETTINGS};
enum QUICKCONFIGENUM {DISABLED = 0, WASD, ESDF, CUSTOM};
enum PLAYERSENUM {PLAYER1 = 0, PLAYER2, PLAYER3, PLAYER4, ALLPLAYERS};
enum DEVICETYPE {MOUSETYPE = 0, KEYBOARDTYPE};
struct PROFILE_STRUCT
{
int BUTTONPRIM[TOTALBUTTONS];
int BUTTONSEC[TOTALBUTTONS];
int SETTINGS[TOTALSETTINGS];
};
// device struct (used for all game input)
struct DEVICE_STRUCT
{
int XPOS, YPOS; // mouse input
int WHEEL; // mouse wheel buffer cool down
int BUTTONPRIM[TOTALBUTTONS]; // button values for primary set (0-1)
int BUTTONSEC[TOTALBUTTONS]; // button values for secondary set (0-1)
int ARROW[4]; // arrow information
};
// plugin spec
#define PLUGIN_TYPE_CONTROLLER 4
#define PLUGIN_NONE 1
#define PLUGIN_MEMPAK 2
#define PLUGIN_RUMBLE_PAK 3 // not implemented for non raw data
#define PLUGIN_TANSFER_PAK 4 // not implemented for non raw data
// Structures (Note: BOOL, WORD, DWORD, HWND are defined in windows.h)
#ifndef _WINDOWS_
typedef unsigned short WORD;
typedef int BOOL;
typedef unsigned long DWORD;
typedef void *HWND;
#endif
typedef struct
{
WORD Version; // Should be set to 0xFBAD
WORD Type; // Set to PLUGIN_TYPE_CONTROLLER
char Name[100]; // Name of the DLL
BOOL Reserved1;
BOOL Reserved2;
} PLUGIN_INFO;
typedef struct
{
BOOL Present;
BOOL RawData;
int Plugin;
} CONTROL;
typedef union
{
DWORD Value;
struct
{
unsigned R_DPAD: 1;
unsigned L_DPAD: 1;
unsigned D_DPAD: 1;
unsigned U_DPAD: 1;
unsigned START_BUTTON: 1;
unsigned Z_TRIG: 1;
unsigned B_BUTTON: 1;
unsigned A_BUTTON: 1;
unsigned R_CBUTTON: 1;
unsigned L_CBUTTON: 1;
unsigned D_CBUTTON: 1;
unsigned U_CBUTTON: 1;
unsigned R_TRIG: 1;
unsigned L_TRIG: 1;
unsigned RELOAD_HACK: 1; // this unused button is reused as a hacked reload button
unsigned RESERVED: 1;
signed Y_AXIS: 8;
signed X_AXIS: 8;
};
} BUTTONS;
File diff suppressed because it is too large. Load diff
-49
View File
@@ -1,49 +0,0 @@
//==========================================================================
// Mouse Injector Plugin
//==========================================================================
// Copyright (C) 2016-2021 Carnivorous
// All rights reserved.
//
// Mouse Injector is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, visit http://www.gnu.org/licenses/gpl-2.0.html
//==========================================================================
#define TICKRATE_OC 2 // 2ms (500 Hz) for overclocked
#define TICKRATE_STOCK 4 // 4ms (250 Hz) for stock speed
#define TICKRATE (emuoverclock ? TICKRATE_OC : TICKRATE_STOCK)
#define TIMESTEP TICKRATE / 1000
#ifdef SPEEDRUN_BUILD // fov/ratio hacks gives unfair advantage, always use default values for speedrun build
#define RATIOFACTOR 1.f
#define OVERRIDEFOV 60
#else
#define RATIOFACTOR (((float)overrideratiowidth / (float)overrideratioheight) / (16.f / 9.f))
#define OVERRIDEFOV overridefov
#endif
extern BUTTONS CONTROLLER[4];
extern struct PROFILE_STRUCT PROFILE[4];
extern struct DEVICE_STRUCT DEVICE[4];
extern const unsigned char **rdramptr;
extern const unsigned char **romptr;
extern int stopthread;
extern int mousetogglekey;
extern int mousetoggle;
extern int mouselockonfocus;
extern int mouseunlockonloss;
extern int configdialogopen;
extern HWND emulatorwindow;
extern int emuoverclock;
extern int overridefov;
extern int overrideratiowidth, overrideratioheight;
extern int geshowcrosshair;
extern int bypassviewmodelfovtweak;
-76
View File
@@ -1,76 +0,0 @@
#Mouse Injector Makefile
#Use with TDM-GCC 4.9.2-tdm-3 or MinGW
#For portable MinGW download Orwell Dev-C++
#mingw32-make.exe -f makefile to compile
#Compiler directories
MINGWDIR = C:/MinGW64/bin/
CC = $(MINGWDIR)gcc
WINDRES = $(MINGWDIR)windres
#Source directories
SRCDIR = ./
MANYMOUSEDIR = $(SRCDIR)manymouse/
GAMESDIR = $(SRCDIR)games/
OBJDIR = $(SRCDIR)obj/
UIDIR = $(SRCDIR)ui/
DLLNAME = $(SRCDIR)Mouse_Injector.dll
#Compiler flags
#USE_DISCORD_PRESENCE = uncomment line to add discord rich presence (requires clean and rebuild)
#SPEEDRUN_BUILD = uncomment line to build speedrun version (requires clean and rebuild)
CFLAGS = -ansi -O2 -m32 -std=c11 -Wall
ifdef USE_DISCORD_PRESENCE
CFLAGS += -DADD_DISCORD_PRESENCE
endif
ifdef SPEEDRUN_BUILD
CFLAGS += -DSPEEDRUN_BUILD
DLLNAME = $(SRCDIR)Mouse_Injector_Speedrun.dll
endif
WARNINGS = -Wextra -pedantic -Wunreachable-code -Wno-parentheses -Wno-strict-aliasing
RESFLAGS = -F pe-i386 --input-format=rc -O coff
#Linker flags
OBJS = $(OBJDIR)maindll.o $(OBJDIR)device.o $(OBJDIR)discord.o $(OBJDIR)manymouse.o $(OBJDIR)windows_wminput.o $(OBJDIR)game.o $(OBJDIR)goldeneye.o $(OBJDIR)perfectdark.o $(OBJDIR)ui.res
LIBS = -static-libgcc
ifdef USE_DISCORD_PRESENCE
LIBS += -L./discord -ldiscord-rpc
endif
LFLAGS = -shared $(OBJS) -o $(DLLNAME) $(LIBS) -m32 -s -Wl,--add-stdcall-alias
#Main recipes
mouseinjector: $(OBJS)
$(CC) $(LFLAGS)
all: clean mouseinjector
#Individual recipes
$(OBJDIR)maindll.o: $(SRCDIR)maindll.c $(SRCDIR)global.h $(SRCDIR)maindll.h $(SRCDIR)device.h $(SRCDIR)discord.h $(UIDIR)ui.rc $(UIDIR)resource.h $(SRCDIR)vkey.h
$(CC) -c $(SRCDIR)maindll.c -o $(OBJDIR)maindll.o $(CFLAGS) $(WARNINGS) -Wno-unused-parameter
$(OBJDIR)device.o: $(SRCDIR)device.c $(SRCDIR)global.h $(SRCDIR)device.h $(SRCDIR)maindll.h $(MANYMOUSEDIR)manymouse.h $(GAMESDIR)game.h
$(CC) -c $(SRCDIR)device.c -o $(OBJDIR)device.o $(CFLAGS) $(WARNINGS)
$(OBJDIR)discord.o: $(SRCDIR)discord.c $(SRCDIR)global.h $(SRCDIR)discord.h $(SRCDIR)maindll.h $(GAMESDIR)game.h $(GAMESDIR)memory.h
$(CC) -c $(SRCDIR)discord.c -o $(OBJDIR)discord.o $(CFLAGS) $(WARNINGS)
$(OBJDIR)manymouse.o: $(MANYMOUSEDIR)manymouse.c $(MANYMOUSEDIR)manymouse.h
$(CC) -c $(MANYMOUSEDIR)manymouse.c -o $(OBJDIR)manymouse.o $(CFLAGS) $(WARNINGS)
$(OBJDIR)windows_wminput.o: $(MANYMOUSEDIR)windows_wminput.c $(MANYMOUSEDIR)manymouse.h
$(CC) -c $(MANYMOUSEDIR)windows_wminput.c -o $(OBJDIR)windows_wminput.o $(CFLAGS)
$(OBJDIR)game.o: $(GAMESDIR)game.c $(GAMESDIR)game.h
$(CC) -c $(GAMESDIR)game.c -o $(OBJDIR)game.o $(CFLAGS) $(WARNINGS)
$(OBJDIR)goldeneye.o: $(GAMESDIR)goldeneye.c $(SRCDIR)global.h $(SRCDIR)device.h $(SRCDIR)maindll.h $(GAMESDIR)game.h $(GAMESDIR)memory.h
$(CC) -c $(GAMESDIR)goldeneye.c -o $(OBJDIR)goldeneye.o $(CFLAGS) $(WARNINGS)
$(OBJDIR)perfectdark.o: $(GAMESDIR)perfectdark.c $(SRCDIR)global.h $(SRCDIR)device.h $(SRCDIR)maindll.h $(GAMESDIR)game.h $(GAMESDIR)memory.h
$(CC) -c $(GAMESDIR)perfectdark.c -o $(OBJDIR)perfectdark.o $(CFLAGS) $(WARNINGS)
$(OBJDIR)ui.res: $(UIDIR)ui.rc $(UIDIR)resource.h
$(WINDRES) -i $(UIDIR)ui.rc -o $(OBJDIR)ui.res $(RESFLAGS)
clean:
rm -f $(SRCDIR)*.dll $(OBJDIR)*.o $(OBJDIR)*.res
@@ -1,23 +0,0 @@
Copyright (c) 2005-2012 Ryan C. Gordon and others.
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from
the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Ryan C. Gordon <icculus@icculus.org>
@@ -1,92 +0,0 @@
/*
* ManyMouse foundation code; apps talks to this and it talks to the lowlevel
* code for various platforms.
*
* Please see the file LICENSE.txt in the source's root directory.
*
* This file written by Ryan C. Gordon.
*/
#include <stdlib.h>
#include "manymouse.h"
static const char *manymouse_copyright =
"ManyMouse " MANYMOUSE_VERSION " copyright (c) 2005-2012 Ryan C. Gordon.";
extern const ManyMouseDriver *ManyMouseDriver_windows;
/*
* These have to be in the favored order...obviously it doesn't matter if the
* Linux driver comes before or after the Windows one, since one won't
* exist on a given platform, but things like Mac OS X's hidmanager (which
* only works on OS X 10.5 and later) should come before Mac OS X's
* hidutilities (which works on older systems, but may stop working in 10.6
* and later). In the Mac OS X case, you want to try the newer tech, and if
* it's not available (on 10.4 or earlier), fall back to trying the legacy
* code.
*/
static const ManyMouseDriver **mice_drivers[] =
{
&ManyMouseDriver_windows,
};
static const ManyMouseDriver *driver = NULL;
int ManyMouse_Init(void)
{
const int upper = (sizeof (mice_drivers) / sizeof (mice_drivers[0]));
int i;
int retval = -1;
/* impossible test to keep manymouse_copyright linked into the binary. */
if (manymouse_copyright == NULL)
return -1;
if (driver != NULL)
return -1;
for (i = 0; (i < upper) && (driver == NULL); i++)
{
const ManyMouseDriver *this_driver = *(mice_drivers[i]);
if (this_driver != NULL) /* if not built for this platform, skip it. */
{
const int mice = this_driver->init();
if (mice > retval)
retval = mice; /* may move from "error" to "no mice found". */
if (mice >= 0)
driver = this_driver;
} /* if */
} /* for */
return retval;
} /* ManyMouse_Init */
void ManyMouse_Quit(void)
{
if (driver != NULL)
{
driver->quit();
driver = NULL;
} /* if */
} /* ManyMouse_Quit */
const char *ManyMouse_DriverName(void)
{
return (driver) ? driver->driver_name : NULL;
} /* ManyMouse_DriverName */
const char *ManyMouse_DeviceName(unsigned int index, unsigned int iskeyboard)
{
return (driver) ? driver->name(index, iskeyboard) : NULL;
} /* ManyMouse_DeviceName */
int ManyMouse_PollEvent(ManyMouseEvent *event)
{
return (driver) ? driver->poll(event) : 0;
} /* ManyMouse_PollEvent */
/* end of manymouse.c ... */
@@ -1,65 +0,0 @@
/*
* ManyMouse main header. Include this from your app.
*
* Please see the file LICENSE.txt in the source's root directory.
*
* This file written by Ryan C. Gordon.
*/
#ifndef _INCLUDE_MANYMOUSE_H_
#define _INCLUDE_MANYMOUSE_H_
#ifdef __cplusplus
extern "C" {
#endif
#define MANYMOUSE_VERSION "0.0.3"
typedef enum
{
MANYMOUSE_EVENT_ABSMOTION = 0,
MANYMOUSE_EVENT_RELMOTION,
MANYMOUSE_EVENT_BUTTON,
MANYMOUSE_EVENT_SCROLL,
MANYMOUSE_EVENT_KEYBOARD,
MANYMOUSE_EVENT_DISCONNECT,
MANYMOUSE_EVENT_MAX
} ManyMouseEventType;
typedef struct
{
ManyMouseEventType type;
unsigned int device;
unsigned int item;
int value;
int minval;
int maxval;
unsigned int iskeyboard;
} ManyMouseEvent;
/* internal use only. */
typedef struct
{
const char *driver_name;
int (*init)(void);
void (*quit)(void);
const char *(*name)(unsigned int index, unsigned int iskeyboard);
int (*poll)(ManyMouseEvent *event);
} ManyMouseDriver;
int ManyMouse_Init(void);
const char *ManyMouse_DriverName(void);
void ManyMouse_Quit(void);
const char *ManyMouse_DeviceName(unsigned int index, unsigned int iskeyboard);
int ManyMouse_PollEvent(ManyMouseEvent *event);
#ifdef __cplusplus
}
#endif
#endif /* !defined _INCLUDE_MANYMOUSE_H_ */
/* end of manymouse.h ... */
@@ -1,758 +0,0 @@
/*
* Support for Windows via the WM_INPUT message.
*
* Please see the file LICENSE.txt in the source's root directory.
*
* This file written by Ryan C. Gordon.
*/
#include "manymouse.h"
#if (defined(_WIN32) || defined(_WINDOWS) || defined(__CYGWIN__))
/* WinUser.h won't include rawinput stuff without this... */
#if (_WIN32_WINNT < 0x0501)
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#include <setupapi.h>
#include <malloc.h> /* needed for alloca(). */
/* Cygwin's headers don't have WM_INPUT right now... */
#ifndef WM_INPUT
#define WM_INPUT 0x00FF
#endif
/* that should be enough, knock on wood. */
#define MAX_MICE 32
/*
* Just trying to avoid malloc() here...we statically allocate a buffer
* for events and treat it as a ring buffer.
*/
/* !!! FIXME: tweak this? */
#define MAX_EVENTS 1024
static ManyMouseEvent input_events[MAX_EVENTS];
static volatile int input_events_read = 0;
static volatile int input_events_write = 0;
static int available_devices = 0;
static int did_api_lookup = 0;
static HWND raw_hwnd = NULL;
static const char *class_name = "ManyMouseRawInputCatcher";
static const char *win_name = "ManyMouseRawInputMsgWindow";
static ATOM class_atom = 0;
static CRITICAL_SECTION mutex;
typedef struct
{
HANDLE handle;
UINT iskeyboard;
char name[256];
} MouseStruct;
static MouseStruct mice[MAX_MICE];
/*
* The RawInput APIs only exist in Windows XP and later, so you want this
* to fail gracefully on earlier systems instead of refusing to start the
* process due to missing symbols. To this end, we do a symbol lookup on
* User32.dll, etc to get the entry points.
*
* A lot of these are available all the way back to the start of win32 in
* Windows 95 and WinNT 3.1, but just so you don't have to track down any
* import libraries, I've added those here, too. That fits well with the
* idea of just adding the sources to your build and going forward.
*/
static UINT (WINAPI *pGetRawInputDeviceList)(PRAWINPUTDEVICELIST,PUINT,UINT);
/* !!! FIXME: use unicode version */
static UINT (WINAPI *pGetRawInputDeviceInfoA)(HANDLE,UINT,LPVOID,PUINT);
static BOOL (WINAPI *pRegisterRawInputDevices)(PCRAWINPUTDEVICE,UINT,UINT);
static LRESULT (WINAPI *pDefRawInputProc)(PRAWINPUT *,INT,UINT);
static UINT (WINAPI *pGetRawInputBuffer)(PRAWINPUT,PUINT,UINT);
static UINT (WINAPI *pGetRawInputData)(HRAWINPUT,UINT,LPVOID,PUINT,UINT);
static HWND (WINAPI *pCreateWindowExA)(DWORD,LPCTSTR,LPCTSTR,DWORD,int,int,int,int,HWND,HMENU,HINSTANCE,LPVOID);
static ATOM (WINAPI *pRegisterClassExA)(CONST WNDCLASSEX *);
static LRESULT (WINAPI *pDefWindowProcA)(HWND,UINT,WPARAM,LPARAM);
static BOOL (WINAPI *pUnregisterClassA)(LPCTSTR,HINSTANCE);
static HMODULE (WINAPI *pGetModuleHandleA)(LPCTSTR);
static BOOL (WINAPI *pPeekMessageA)(LPMSG,HWND,UINT,UINT,UINT);
static BOOL (WINAPI *pTranslateMessage)(const MSG *);
static LRESULT (WINAPI *pDispatchMessageA)(const MSG *);
static BOOL (WINAPI *pDestroyWindow)(HWND);
static void (WINAPI *pInitializeCriticalSection)(LPCRITICAL_SECTION);
static void (WINAPI *pEnterCriticalSection)(LPCRITICAL_SECTION);
static void (WINAPI *pLeaveCriticalSection)(LPCRITICAL_SECTION);
static void (WINAPI *pDeleteCriticalSection)(LPCRITICAL_SECTION);
static DWORD (WINAPI *pGetLastError)(void);
static HDEVINFO (WINAPI *pSetupDiGetClassDevsA)(LPGUID, LPCTSTR, HWND, DWORD);
static BOOL (WINAPI *pSetupDiEnumDeviceInfo)(HDEVINFO, DWORD, PSP_DEVINFO_DATA);
static BOOL (WINAPI *pSetupDiGetDeviceInstanceIdA)(HDEVINFO, PSP_DEVINFO_DATA, PTSTR, DWORD, PDWORD);
static BOOL (WINAPI *pSetupDiGetDeviceRegistryPropertyA)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD);
static BOOL (WINAPI *pSetupDiDestroyDeviceInfoList)(HDEVINFO);
static int symlookup(HMODULE dll, void **addr, const char *sym)
{
*addr = GetProcAddress(dll, sym);
if (*addr == NULL)
{
FreeLibrary(dll);
return 0;
} /* if */
return 1;
} /* symlookup */
static int find_api_symbols(void)
{
HMODULE dll;
if (did_api_lookup)
return 1;
#define LOOKUP(x) { if (!symlookup(dll, (void **) &p##x, #x)) return 0; }
dll = LoadLibrary(TEXT("user32.dll"));
if (dll == NULL)
return 0;
LOOKUP(GetRawInputDeviceInfoA);
LOOKUP(RegisterRawInputDevices);
LOOKUP(GetRawInputDeviceList);
LOOKUP(DefRawInputProc);
LOOKUP(GetRawInputBuffer);
LOOKUP(GetRawInputData);
LOOKUP(CreateWindowExA);
LOOKUP(RegisterClassExA);
LOOKUP(UnregisterClassA);
LOOKUP(DefWindowProcA);
LOOKUP(PeekMessageA);
LOOKUP(TranslateMessage);
LOOKUP(DispatchMessageA);
LOOKUP(DestroyWindow);
dll = LoadLibrary(TEXT("kernel32.dll"));
if (dll == NULL)
return 0;
LOOKUP(GetModuleHandleA);
LOOKUP(GetLastError);
LOOKUP(InitializeCriticalSection);
LOOKUP(EnterCriticalSection);
LOOKUP(LeaveCriticalSection);
LOOKUP(DeleteCriticalSection);
dll = LoadLibrary(TEXT("setupapi.dll"));
if (dll == NULL)
return 0;
LOOKUP(SetupDiGetClassDevsA);
LOOKUP(SetupDiEnumDeviceInfo);
LOOKUP(SetupDiGetDeviceInstanceIdA);
LOOKUP(SetupDiGetDeviceRegistryPropertyA);
LOOKUP(SetupDiDestroyDeviceInfoList);
#undef LOOKUP
did_api_lookup = 1;
return 1;
} /* find_api_symbols */
/* Some simple functions to avoid C runtime dependency... */
static char make_upper(const char a)
{
return ((a >= 'a') && (a <= 'z')) ? (a - ('a' - 'A')) : a;
} /* make_upper */
static void make_string_upper(char *str)
{
char *ptr;
for (ptr = str; *ptr; ptr++)
*ptr = make_upper(*ptr);
} /* make_string_upper */
static int string_compare(const char *a, const char *b)
{
while (1)
{
const char cha = *(a++);
const char chb = *(b++);
if (cha < chb)
return -1;
else if (cha > chb)
return 1;
else if (cha == '\0')
return 0;
} /* while */
return 0;
} /* string_compare */
static size_t string_length(const char *a)
{
size_t retval;
for (retval = 0; *(a++); retval++) { /* spin. */ }
return retval;
} /* string_length */
static void queue_event(const ManyMouseEvent *event)
{
/* copy the event info. We'll process it in ManyMouse_PollEvent(). */
CopyMemory(&input_events[input_events_write], event, sizeof (ManyMouseEvent));
input_events_write = ((input_events_write + 1) % MAX_EVENTS);
/* Ring buffer full? Lose oldest event. */
if (input_events_write == input_events_read)
{
/* !!! FIXME: we need to not lose mouse buttons here. */
input_events_read = ((input_events_read + 1) % MAX_EVENTS);
} /* if */
} /* queue_event */
static void queue_from_rawinput(const RAWINPUT *raw)
{
int i;
const RAWINPUTHEADER *header = &raw->header;
const RAWMOUSE *mouse = &raw->data.mouse;
const RAWKEYBOARD *keyboard = &raw->data.keyboard;
ManyMouseEvent event;
if (raw->header.dwType != RIM_TYPEMOUSE && raw->header.dwType != RIM_TYPEKEYBOARD)
return;
for (i = 0; i < available_devices; i++) /* find the device for event. */
{
if (mice[i].handle == header->hDevice)
break;
} /* for */
if (i == available_devices)
return; /* not found?! */
/*
* RAWINPUT packs a bunch of events into one, so we split it up into
* a bunch of ManyMouseEvents here and store them in an internal queue.
* Then ManyMouse_PollEvent() just shuffles items off that queue
* without any complicated processing.
*/
event.device = i;
pEnterCriticalSection(&mutex);
event.iskeyboard = mice[i].iskeyboard;
if(raw->header.dwType == RIM_TYPEKEYBOARD)
{
event.type = MANYMOUSE_EVENT_KEYBOARD;
event.item = keyboard->VKey;
if(keyboard->Message == WM_KEYDOWN || keyboard->Message == WM_SYSKEYDOWN) // pressed down
event.value = 1;
else if(keyboard->Message == WM_KEYUP || keyboard->Message == WM_SYSKEYUP) // pressed up
event.value = 0;
else // unhandled exception
{
pLeaveCriticalSection(&mutex);
return;
}
queue_event(&event);
pLeaveCriticalSection(&mutex);
return;
}
if (mouse->usFlags & MOUSE_MOVE_ABSOLUTE)
{
/* !!! FIXME: How do we get the min and max values for absmotion? */
event.type = MANYMOUSE_EVENT_ABSMOTION;
event.item = 0;
event.value = mouse->lLastX;
queue_event(&event);
event.item = 1;
event.value = mouse->lLastY;
queue_event(&event);
} /* if */
else /*if (mouse->usFlags & MOUSE_MOVE_RELATIVE)*/
{
event.type = MANYMOUSE_EVENT_RELMOTION;
if (mouse->lLastX != 0)
{
event.item = 0;
event.value = mouse->lLastX;
queue_event(&event);
} /* if */
if (mouse->lLastY != 0)
{
event.item = 1;
event.value = mouse->lLastY;
queue_event(&event);
} /* if */
} /* else if */
event.type = MANYMOUSE_EVENT_BUTTON;
#define QUEUE_BUTTON(x) { \
if (mouse->usButtonFlags & RI_MOUSE_BUTTON_##x##_DOWN) { \
event.item = x-1; \
event.value = 1; \
queue_event(&event); \
} \
if (mouse->usButtonFlags & RI_MOUSE_BUTTON_##x##_UP) { \
event.item = x-1; \
event.value = 0; \
queue_event(&event); \
} \
}
QUEUE_BUTTON(1);
QUEUE_BUTTON(2);
QUEUE_BUTTON(3);
QUEUE_BUTTON(4);
QUEUE_BUTTON(5);
#undef QUEUE_BUTTON
if (mouse->usButtonFlags & RI_MOUSE_WHEEL)
{
if (mouse->usButtonData != 0) /* !!! FIXME: can this ever be zero? */
{
event.type = MANYMOUSE_EVENT_SCROLL;
event.item = 0; /* !!! FIXME: horizontal wheel? */
event.value = ( ((SHORT) mouse->usButtonData) > 0) ? 1 : -1;
queue_event(&event);
} /* if */
} /* if */
pLeaveCriticalSection(&mutex);
} /* queue_from_rawinput */
static void wminput_handler(WPARAM wParam, LPARAM lParam)
{
UINT dwSize = 0;
LPBYTE lpb;
pGetRawInputData((HRAWINPUT) lParam, RID_INPUT, NULL, &dwSize,
sizeof (RAWINPUTHEADER));
if (dwSize < sizeof (RAWKEYBOARD))
return; /* unexpected packet? */
lpb = (LPBYTE) alloca(dwSize);
if (lpb == NULL)
return;
if (pGetRawInputData((HRAWINPUT) lParam, RID_INPUT, lpb, &dwSize,
sizeof (RAWINPUTHEADER)) != dwSize)
return;
queue_from_rawinput((RAWINPUT *) lpb);
} /* wminput_handler */
static LRESULT CALLBACK RawWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
if (Msg == WM_INPUT)
wminput_handler(wParam, lParam);
else if (Msg == WM_DESTROY)
return 0;
return pDefWindowProcA(hWnd, Msg, wParam, lParam);
} /* RawWndProc */
static int init_event_queue(void)
{
HINSTANCE hInstance = pGetModuleHandleA(NULL);
WNDCLASSEX wce;
RAWINPUTDEVICE rid[2];
ZeroMemory(input_events, sizeof (input_events));
input_events_read = input_events_write = 0;
ZeroMemory(&wce, sizeof (wce));
wce.cbSize = sizeof(WNDCLASSEX);
wce.lpfnWndProc = RawWndProc;
wce.lpszClassName = class_name;
wce.hInstance = hInstance;
class_atom = pRegisterClassExA(&wce);
if (class_atom == 0)
return 0;
raw_hwnd = pCreateWindowExA(0, class_name, win_name, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, HWND_MESSAGE, NULL, hInstance, NULL);
if (raw_hwnd == NULL)
return 0;
pInitializeCriticalSection(&mutex);
ZeroMemory(rid, sizeof (rid));
rid[0].usUsagePage = 1; /* GenericDesktop page */
rid[0].usUsage = 2; /* GeneralDestop Mouse usage. */
rid[0].dwFlags = RIDEV_INPUTSINK;
rid[0].hwndTarget = raw_hwnd;
rid[1].usUsagePage = 1; /* GenericDesktop page */
rid[1].usUsage = 6; /* GeneralDestop Keyboard usage. */
rid[1].dwFlags = RIDEV_INPUTSINK;
rid[1].hwndTarget = raw_hwnd;
if (!pRegisterRawInputDevices(rid, 2, sizeof (RAWINPUTDEVICE)))
{
pDeleteCriticalSection(&mutex);
return 0;
} /* if */
return 1;
} /* init_event_queue */
static void cleanup_window(void)
{
if (raw_hwnd)
{
MSG Msg;
pDestroyWindow(raw_hwnd);
while (pPeekMessageA(&Msg, raw_hwnd, 0, 0, PM_REMOVE))
{
pTranslateMessage(&Msg);
pDispatchMessageA(&Msg);
} /* while */
raw_hwnd = 0;
} /* if */
if (class_atom)
{
pUnregisterClassA(class_name, pGetModuleHandleA(NULL));
class_atom = 0;
} /* if */
} /* cleanup_window */
static int get_devinfo_data(HDEVINFO devinfo, const char *devinstance,
SP_DEVINFO_DATA *data)
{
DWORD i = 0;
const DWORD bufsize = string_length(devinstance) + 1;
char *buf = (char *) alloca(bufsize);
if (buf == NULL)
return 0;
while (1)
{
ZeroMemory(data, sizeof (SP_DEVINFO_DATA));
data->cbSize = sizeof (SP_DEVINFO_DATA);
if (!pSetupDiEnumDeviceInfo(devinfo, i++, data))
{
if (pGetLastError() == ERROR_NO_MORE_ITEMS)
break;
else
continue;
} /* if */
if (!pSetupDiGetDeviceInstanceIdA(devinfo, data, buf, bufsize, NULL))
continue;
make_string_upper(buf);
if (string_compare(devinstance, buf) == 0)
return 1; /* found it! */
} /* while */
return 0; /* not found. */
} /* get_devinfo_data */
static void get_dev_name_by_instance(const char *devinstance, char *name,
size_t namesize)
{
SP_DEVINFO_DATA devdata;
const DWORD flags = DIGCF_ALLCLASSES | DIGCF_PRESENT;
HDEVINFO devinfo = pSetupDiGetClassDevsA(NULL, NULL, NULL, flags);
if (devinfo == INVALID_HANDLE_VALUE)
return;
if (get_devinfo_data(devinfo, devinstance, &devdata))
{
pSetupDiGetDeviceRegistryPropertyA(devinfo, &devdata, SPDRP_DEVICEDESC,
NULL, (PBYTE) name, namesize, NULL);
} /* if */
pSetupDiDestroyDeviceInfoList(devinfo);
} /* get_dev_name_by_instance */
static void get_device_product_name(char *name, size_t namesize, char *devname)
{
const char default_device_name[] = "Unidentified input device";
*name = '\0'; /* really insane default. */
if (sizeof (default_device_name) >= namesize)
return;
/* in case we can't stumble upon something better... */
CopyMemory(name, default_device_name, sizeof (default_device_name));
/* okay, we're got the device instance. Now find the data for it. */
get_dev_name_by_instance(devname, name, namesize);
} /* get_device_product_name */
static void init_mouse(const RAWINPUTDEVICELIST *dev)
{
const char rdp_ident_kb[] = "ROOT\\RDP_KBD\\";
const char rdp_ident_mi[] = "ROOT\\RDP_MOU\\";
MouseStruct *mouse = &mice[available_devices];
char *buf = NULL;
char *ptr = NULL;
UINT ct = 0;
if (dev->dwType != RIM_TYPEMOUSE && dev->dwType != RIM_TYPEKEYBOARD)
return; /* if not keyboard or mice (some other fruity thing). */
if (pGetRawInputDeviceInfoA(dev->hDevice, RIDI_DEVICENAME, NULL, &ct) < 0)
return;
/* ct == is chars, not bytes, but we used the ASCII version. */
buf = (char *) alloca(ct+1);
if (buf == NULL)
return;
if (pGetRawInputDeviceInfoA(dev->hDevice, RIDI_DEVICENAME, buf, &ct) < 0)
return;
buf[ct] = '\0'; /* make sure it's null-terminated. */
/* XP starts these strings with "\\??\\" ... Vista does "\\\\?\\". :/ */
while ((*buf == '?') || (*buf == '\\'))
{
buf++;
ct--;
} /* while */
/* This string tap dancing gets us the device instance id. */
for (ptr = buf; *ptr; ptr++) /* convert '#' to '\\' ... */
{
char ch = *ptr;
if (ch == '#')
*ptr = '\\';
else if (ch == '{') /* hit the GUID part of the string. */
{
if (*(ptr-1) == '\\')
ptr--;
break;
} /* else if */
} /* for */
*ptr = '\0';
make_string_upper(buf);
/*
* Apparently there's a fake "RDP" device...I guess this is
* "Remote Desktop Protocol" for controlling the system pointer
* remotely via Windows Remote Desktop, but that's just a guess.
* At any rate, we don't want that device, so skip it if detected.
*
* Idea for this found here:
* http://link.mywwwserver.com/~jstookey/arcade/rawmouse/raw_mouse.c
*/
/* avoiding memcmp here so we don't get a C runtime dependency... */
if (ct >= sizeof (rdp_ident_kb) - 1)
{
int i;
for (i = 0; i < sizeof (rdp_ident_kb) - 1; i++)
{
if (buf[i] != rdp_ident_kb[i])
break;
} /* for */
if (i == sizeof (rdp_ident_kb) - 1)
return; /* this is an RDP thing. Skip this device. */
} /* if */
if (ct >= sizeof (rdp_ident_mi) - 1)
{
int i;
for (i = 0; i < sizeof (rdp_ident_mi) - 1; i++)
{
if (buf[i] != rdp_ident_mi[i])
break;
} /* for */
if (i == sizeof (rdp_ident_mi) - 1)
return; /* this is an RDP thing. Skip this device. */
} /* if */
/* accept this mouse! */
ZeroMemory(mouse, sizeof (MouseStruct));
get_device_product_name(mouse->name, sizeof (mouse->name), buf);
mouse->handle = dev->hDevice;
mouse->iskeyboard = dev->dwType == RIM_TYPEKEYBOARD ? 1 : 0;
available_devices++;
} /* init_mouse */
static int windows_wminput_init(void)
{
RAWINPUTDEVICELIST *devlist = NULL;
UINT ct = 0;
UINT i;
available_devices = 0;
if (!find_api_symbols()) /* only supported on WinXP and later. */
return -1;
pGetRawInputDeviceList(NULL, &ct, sizeof (RAWINPUTDEVICELIST));
if (ct == 0) /* no devices. */
return 0;
devlist = (PRAWINPUTDEVICELIST) alloca(sizeof (RAWINPUTDEVICELIST) * ct);
pGetRawInputDeviceList(devlist, &ct, sizeof (RAWINPUTDEVICELIST));
for (i = 0; i < ct; i++)
init_mouse(&devlist[i]);
if (!init_event_queue())
{
cleanup_window();
available_devices = 0;
} /* if */
return available_devices;
} /* windows_wminput_init */
static void windows_wminput_quit(void)
{
/* unregister WM_INPUT devices... */
RAWINPUTDEVICE rid[2];
ZeroMemory(rid, sizeof (rid));
rid[0].usUsagePage = 1; /* GenericDesktop page */
rid[0].usUsage = 2; /* GeneralDestop Mouse usage. */
rid[0].dwFlags |= RIDEV_REMOVE;
rid[0].hwndTarget = raw_hwnd;
rid[1].usUsagePage = 1; /* GenericDesktop page */
rid[1].usUsage = 6; /* GeneralDestop Keyboard usage. */
rid[1].dwFlags |= RIDEV_REMOVE;
rid[1].hwndTarget = raw_hwnd;
pRegisterRawInputDevices(rid, 2, sizeof (RAWINPUTDEVICE));
cleanup_window();
available_devices = 0;
pDeleteCriticalSection(&mutex);
} /* windows_wminput_quit */
static const char *windows_wminput_name(unsigned int index, unsigned int iskeyboard)
{
return (index < available_devices && mice[index].iskeyboard == iskeyboard) ? mice[index].name : NULL;
} /* windows_wminput_name */
/*
* Windows doesn't send a WM_INPUT event when you unplug a mouse,
* so we try to do a basic query by device handle here; if the
* query fails, we assume the device has vanished and generate a
* disconnect.
*/
static int check_for_disconnects(ManyMouseEvent *ev)
{
/*
* (i) is static so we iterate through all mice round-robin and check
* one mouse per call to ManyMouse_PollEvent(). This makes this test O(1).
*/
static unsigned int i = 0;
MouseStruct *mouse = NULL;
if (++i >= available_devices) /* check first in case of redetect */
i = 0;
mouse = &mice[i];
if (mouse->handle != NULL) /* not NULL == still plugged in. */
{
UINT size = 0;
UINT rc = pGetRawInputDeviceInfoA(mouse->handle, RIDI_DEVICEINFO,
NULL, &size);
if (rc == (UINT) -1) /* failed...probably unplugged... */
{
mouse->handle = NULL;
ev->type = MANYMOUSE_EVENT_DISCONNECT;
ev->device = i;
ev->iskeyboard = mouse->iskeyboard;
return 1;
} /* if */
} /* if */
return 0; /* no disconnect event this time. */
} /* check_for_disconnects */
static int windows_wminput_poll(ManyMouseEvent *ev)
{
MSG Msg; /* run the queue for WM_INPUT messages, etc ... */
int found = 0;
/* ...favor existing events in the queue... */
pEnterCriticalSection(&mutex);
if (input_events_read != input_events_write) /* no events if equal. */
{
CopyMemory(ev, &input_events[input_events_read], sizeof (*ev));
input_events_read = ((input_events_read + 1) % MAX_EVENTS);
found = 1;
} /* if */
pLeaveCriticalSection(&mutex);
if (!found)
{
/* pump Windows for new hardware events... */
while (pPeekMessageA(&Msg, raw_hwnd, 0, 0, PM_REMOVE))
{
pTranslateMessage(&Msg);
pDispatchMessageA(&Msg);
} /* while */
/* In case something new came in, give it to the app... */
pEnterCriticalSection(&mutex);
if (input_events_read != input_events_write) /* no events if equal. */
{
CopyMemory(ev, &input_events[input_events_read], sizeof (*ev));
input_events_read = ((input_events_read + 1) % MAX_EVENTS);
found = 1;
} /* if */
pLeaveCriticalSection(&mutex);
} /* if */
/*
* Check for disconnects if queue is totally empty and Windows didn't
* report anything new at this time. This ensures that we don't send a
* disconnect event through ManyMouse and then later give a valid
* event to the app for a device that is now missing.
*/
if (!found)
found = check_for_disconnects(ev);
return found;
} /* windows_wminput_poll */
static const ManyMouseDriver ManyMouseDriver_interface =
{
"Windows XP and later WM_INPUT interface",
windows_wminput_init,
windows_wminput_quit,
windows_wminput_name,
windows_wminput_poll
};
const ManyMouseDriver *ManyMouseDriver_windows = &ManyMouseDriver_interface;
#else
const ManyMouseDriver *ManyMouseDriver_windows = 0;
#endif /* ifdef Windows blocker */
/* end of windows_wminput.c ... */
-127
View File
@@ -1,127 +0,0 @@
//==========================================================================
// Mouse Injector Plugin
//==========================================================================
// Copyright (C) 2016-2021 Carnivorous
// All rights reserved.
//
// Mouse Injector is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, visit http://www.gnu.org/licenses/gpl-2.0.html
//==========================================================================
#ifndef IDC_STATIC
#define IDC_STATIC (-1)
#endif
#define IDC_CONFIGWINDOW 1
#define IDC_CONFIGBOXINFO 100
#define IDC_STATICPRIM 101
#define IDC_STATICSEC 102
#define IDC_CONFIGBOX 103
#define IDC_LABEL00 104
#define IDC_LABEL01 105
#define IDC_LABEL02 106
#define IDC_LABEL03 107
#define IDC_LABEL04 108
#define IDC_LABEL05 109
#define IDC_LABEL06 110
#define IDC_LABEL07 111
#define IDC_LABEL08 112
#define IDC_LABEL09 113
#define IDC_LABEL10 114
#define IDC_LABEL11 115
#define IDC_LABEL12 116
#define IDC_LABEL13 117
#define IDC_LABEL14 118
#define IDC_LABEL15 119
#define IDC_LABEL16 120
#define IDC_LABEL17 121
#define IDC_PRIMARY00 122
#define IDC_PRIMARY01 123
#define IDC_PRIMARY02 124
#define IDC_PRIMARY03 125
#define IDC_PRIMARY04 126
#define IDC_PRIMARY05 127
#define IDC_PRIMARY06 128
#define IDC_PRIMARY07 129
#define IDC_PRIMARY08 130
#define IDC_PRIMARY09 131
#define IDC_PRIMARY10 132
#define IDC_PRIMARY11 133
#define IDC_PRIMARY12 134
#define IDC_PRIMARY13 135
#define IDC_PRIMARY14 136
#define IDC_PRIMARY15 137
#define IDC_PRIMARY16 138
#define IDC_PRIMARY17 139
#define IDC_SECONDARY00 140
#define IDC_SECONDARY01 141
#define IDC_SECONDARY02 142
#define IDC_SECONDARY03 143
#define IDC_SECONDARY04 144
#define IDC_SECONDARY05 145
#define IDC_SECONDARY06 146
#define IDC_SECONDARY07 147
#define IDC_SECONDARY08 148
#define IDC_SECONDARY09 149
#define IDC_SECONDARY10 150
#define IDC_SECONDARY11 151
#define IDC_SECONDARY12 152
#define IDC_SECONDARY13 153
#define IDC_SECONDARY14 154
#define IDC_SECONDARY15 155
#define IDC_SECONDARY16 156
#define IDC_SECONDARY17 157
#define IDC_LOCK_LABEL 158
#define IDC_LOCK 159
#define IDC_MOUSESELECT 160
#define IDC_KEYBOARDSELECT 161
#define IDC_MOUSESELECTINFO 162
#define IDC_KEYBOARDSELECTINFO 163
#define IDC_SLIDER_STATIC00 164
#define IDC_SLIDER_DISPLAY00 165
#define IDC_SLIDER_STATIC01 166
#define IDC_SLIDER_DISPLAY01 167
#define IDC_SLIDER_STATIC02 168
#define IDC_SLIDER_DISPLAY02 169
#define IDC_SLIDER00 170
#define IDC_SLIDER01 171
#define IDC_SLIDER02 172
#define IDC_INVERTPITCH 173
#define IDC_CROUCHTOGGLE 174
#define IDC_GECURSORAIMING 175
#define IDC_PDCURSORAIMING 176
#define IDC_ALLPLAYERS 177
#define IDC_RATIOSTATIC 178
#define IDC_RATIOWIDTH 179
#define IDC_RATIOSTATICX 180
#define IDC_RATIOHEIGHT 181
#define IDC_RESETFOV 182
#define IDC_FOV_DEGREES 183
#define IDC_FOV 184
#define IDC_FOV_NOTE 185
#define IDC_GESHOWCROSSHAIR 186
#define IDC_BYPASSVIEWMODELFOVWEAK 187
#define IDC_INFOBOX 188
#define IDC_INFO 189
#define IDC_REVERT 190
#define IDC_OK 191
#define IDC_CANCEL 192
#define IDC_CLEAR 193
#define IDC_HELPPOPUP 194
#define IDC_PLAYER1 195
#define IDC_PLAYER2 196
#define IDC_PLAYER3 197
#define IDC_PLAYER4 198
#define IDC_DETECTDEVICE 199
#define IDC_LOCKONFOCUS 200
#define IDC_UNLOCKONWINLOSS 201
#define IDC_PARTITION IDC_STATIC
-165
View File
@@ -1,165 +0,0 @@
//==========================================================================
// Mouse Injector Plugin
//==========================================================================
// Copyright (C) 2016-2021 Carnivorous
// All rights reserved.
//
// Mouse Injector is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, visit http://www.gnu.org/licenses/gpl-2.0.html
//==========================================================================
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#include "resource.h"
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
IDC_CONFIGWINDOW DIALOGEX 0, 0, 470, 368
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_CLIPSIBLINGS | WS_POPUP
EXSTYLE WS_EX_CONTROLPARENT
CAPTION "Mouse Injector - Input Settings"
FONT 8, "MS Shell Dlg", 0, 0, 0
{
AUTORADIOBUTTON "Player 1", IDC_PLAYER1, 11, 8, 41, 8, WS_GROUP | WS_TABSTOP, WS_EX_LEFT
AUTORADIOBUTTON "Player 2", IDC_PLAYER2, 56, 8, 41, 8, WS_TABSTOP, WS_EX_LEFT
AUTORADIOBUTTON "Player 3", IDC_PLAYER3, 101, 8, 41, 8, WS_TABSTOP, WS_EX_LEFT
AUTORADIOBUTTON "Player 4", IDC_PLAYER4, 146, 8, 41, 8, WS_TABSTOP, WS_EX_LEFT
PUSHBUTTON "Detect Input Devices", IDC_DETECTDEVICE, 375, 7, 76, 12, NOT WS_VISIBLE, WS_EX_LEFT
CTEXT "", IDC_PARTITION, 7, 22, 456, 2, NOT WS_TABSTOP | SS_CENTER | SS_SUNKEN, WS_EX_LEFT
RTEXT "Profile", IDC_CONFIGBOXINFO, 17, 32, 70, 12, SS_RIGHT | SS_CENTERIMAGE, WS_EX_RIGHT
COMBOBOX IDC_CONFIGBOX, 97, 32, 150, 120, WS_TABSTOP | WS_VSCROLL | CBS_DROPDOWNLIST, WS_EX_LEFT
CTEXT "Primary", IDC_STATICPRIM, 97, 47, 70, 15, SS_CENTER | SS_CENTERIMAGE, WS_EX_LEFT
CTEXT "Secondary", IDC_STATICSEC, 177, 47, 70, 15, SS_CENTER | SS_CENTERIMAGE, WS_EX_LEFT
RTEXT "Forward", IDC_LABEL00, 17, 62, 70, 15, SS_RIGHT | SS_CENTERIMAGE, WS_EX_TRANSPARENT
PUSHBUTTON "", IDC_PRIMARY00, 97, 63, 70, 13, BS_FLAT, WS_EX_LEFT
PUSHBUTTON "", IDC_SECONDARY00, 177, 63, 70, 13, BS_FLAT, WS_EX_LEFT
RTEXT "Backwards", IDC_LABEL01, 17, 77, 70, 15, SS_RIGHT | SS_CENTERIMAGE, WS_EX_TRANSPARENT
PUSHBUTTON "", IDC_PRIMARY01, 97, 78, 70, 13, BS_FLAT, WS_EX_LEFT
PUSHBUTTON "", IDC_SECONDARY01, 177, 78, 70, 13, BS_FLAT, WS_EX_LEFT
RTEXT "Strafe Left", IDC_LABEL02, 17, 92, 70, 15, SS_RIGHT | SS_CENTERIMAGE, WS_EX_TRANSPARENT
PUSHBUTTON "", IDC_PRIMARY02, 97, 93, 70, 13, BS_FLAT, WS_EX_LEFT
PUSHBUTTON "", IDC_SECONDARY02, 177, 93, 70, 13, BS_FLAT, WS_EX_LEFT
RTEXT "Strafe Right", IDC_LABEL03, 17, 107, 70, 15, SS_RIGHT | SS_CENTERIMAGE, WS_EX_TRANSPARENT
PUSHBUTTON "", IDC_PRIMARY03, 97, 108, 70, 13, BS_FLAT, WS_EX_LEFT
PUSHBUTTON "", IDC_SECONDARY03, 177, 108, 70, 13, BS_FLAT, WS_EX_LEFT
RTEXT "Fire", IDC_LABEL04, 17, 122, 70, 15, SS_RIGHT | SS_CENTERIMAGE, WS_EX_TRANSPARENT
PUSHBUTTON "", IDC_PRIMARY04, 97, 123, 70, 13, BS_FLAT, WS_EX_LEFT
PUSHBUTTON "", IDC_SECONDARY04, 177, 123, 70, 13, BS_FLAT, WS_EX_LEFT
RTEXT "Aim", IDC_LABEL05, 17, 137, 70, 15, SS_RIGHT | SS_CENTERIMAGE, WS_EX_TRANSPARENT
PUSHBUTTON "", IDC_PRIMARY05, 97, 138, 70, 13, BS_FLAT, WS_EX_LEFT
PUSHBUTTON "", IDC_SECONDARY05, 177, 138, 70, 13, BS_FLAT, WS_EX_LEFT
RTEXT "Reload", IDC_LABEL06, 17, 152, 70, 15, SS_RIGHT | SS_CENTERIMAGE, WS_EX_TRANSPARENT
PUSHBUTTON "", IDC_PRIMARY06, 97, 153, 70, 13, BS_FLAT, WS_EX_LEFT
PUSHBUTTON "", IDC_SECONDARY06, 177, 153, 70, 13, BS_FLAT, WS_EX_LEFT
RTEXT "Next Weapon/Accept", IDC_LABEL07, 17, 167, 70, 15, SS_RIGHT | SS_CENTERIMAGE, WS_EX_TRANSPARENT
PUSHBUTTON "", IDC_PRIMARY07, 97, 168, 70, 13, BS_FLAT, WS_EX_LEFT
PUSHBUTTON "", IDC_SECONDARY07, 177, 168, 70, 13, BS_FLAT, WS_EX_LEFT
RTEXT "Activate/Cancel", IDC_LABEL08, 17, 182, 70, 15, SS_RIGHT | SS_CENTERIMAGE, WS_EX_TRANSPARENT
PUSHBUTTON "", IDC_PRIMARY08, 97, 183, 70, 13, BS_FLAT, WS_EX_LEFT
PUSHBUTTON "", IDC_SECONDARY08, 177, 183, 70, 13, BS_FLAT, WS_EX_LEFT
RTEXT "Start", IDC_LABEL09, 17, 197, 70, 15, SS_RIGHT | SS_CENTERIMAGE, WS_EX_TRANSPARENT
PUSHBUTTON "", IDC_PRIMARY09, 97, 198, 70, 13, BS_FLAT, WS_EX_LEFT
PUSHBUTTON "", IDC_SECONDARY09, 177, 198, 70, 13, BS_FLAT, WS_EX_LEFT
RTEXT "Crouch", IDC_LABEL10, 17, 212, 70, 15, SS_RIGHT | SS_CENTERIMAGE, WS_EX_TRANSPARENT
PUSHBUTTON "", IDC_PRIMARY10, 97, 213, 70, 13, BS_FLAT, WS_EX_LEFT
PUSHBUTTON "", IDC_SECONDARY10, 177, 213, 70, 13, BS_FLAT, WS_EX_LEFT
RTEXT "(PD) Kneel", IDC_LABEL11, 17, 227, 70, 15, SS_RIGHT | SS_CENTERIMAGE, WS_EX_TRANSPARENT
PUSHBUTTON "", IDC_PRIMARY11, 97, 228, 70, 13, BS_FLAT, WS_EX_LEFT
PUSHBUTTON "", IDC_SECONDARY11, 177, 228, 70, 13, BS_FLAT, WS_EX_LEFT
RTEXT "Previous Weapon", IDC_LABEL12, 17, 242, 70, 15, SS_RIGHT | SS_CENTERIMAGE, WS_EX_TRANSPARENT
PUSHBUTTON "", IDC_PRIMARY12, 97, 243, 70, 13, BS_FLAT, WS_EX_LEFT
PUSHBUTTON "", IDC_SECONDARY12, 177, 243, 70, 13, BS_FLAT, WS_EX_LEFT
RTEXT "Next Weapon", IDC_LABEL13, 17, 257, 70, 15, SS_RIGHT | SS_CENTERIMAGE, WS_EX_TRANSPARENT
PUSHBUTTON "", IDC_PRIMARY13, 97, 258, 70, 13, BS_FLAT, WS_EX_LEFT
PUSHBUTTON "", IDC_SECONDARY13, 177, 258, 70, 13, BS_FLAT, WS_EX_LEFT
RTEXT "Analog Up", IDC_LABEL14, 17, 272, 70, 15, SS_RIGHT | SS_CENTERIMAGE, WS_EX_TRANSPARENT
PUSHBUTTON "", IDC_PRIMARY14, 97, 273, 70, 13, BS_FLAT, WS_EX_LEFT
PUSHBUTTON "", IDC_SECONDARY14, 177, 273, 70, 13, BS_FLAT, WS_EX_LEFT
RTEXT "Analog Down", IDC_LABEL15, 17, 287, 70, 15, SS_RIGHT | SS_CENTERIMAGE, WS_EX_TRANSPARENT
PUSHBUTTON "", IDC_PRIMARY15, 97, 288, 70, 13, BS_FLAT, WS_EX_LEFT
PUSHBUTTON "", IDC_SECONDARY15, 177, 288, 70, 13, BS_FLAT, WS_EX_LEFT
RTEXT "Analog Left", IDC_LABEL16, 17, 301, 70, 15, SS_RIGHT | SS_CENTERIMAGE, WS_EX_TRANSPARENT
PUSHBUTTON "", IDC_PRIMARY16, 97, 303, 70, 13, BS_FLAT, WS_EX_LEFT
PUSHBUTTON "", IDC_SECONDARY16, 177, 303, 70, 13, BS_FLAT, WS_EX_LEFT
RTEXT "Analog Right", IDC_LABEL17, 17, 316, 70, 15, SS_RIGHT | SS_CENTERIMAGE, WS_EX_TRANSPARENT
PUSHBUTTON "", IDC_PRIMARY17, 97, 318, 70, 13, BS_FLAT, WS_EX_LEFT
PUSHBUTTON "", IDC_SECONDARY17, 177, 318, 70, 13, BS_FLAT, WS_EX_LEFT
RTEXT "Mouse", IDC_MOUSESELECTINFO, 265, 32, 31, 12, SS_RIGHT | SS_CENTERIMAGE, WS_EX_RIGHT
COMBOBOX IDC_MOUSESELECT, 301, 32, 151, 120, WS_TABSTOP | WS_VSCROLL | CBS_DROPDOWNLIST, WS_EX_LEFT
RTEXT "Keyboard", IDC_KEYBOARDSELECTINFO, 265, 49, 31, 12, SS_RIGHT | SS_CENTERIMAGE, WS_EX_RIGHT
COMBOBOX IDC_KEYBOARDSELECT, 301, 49, 151, 120, WS_TABSTOP | WS_VSCROLL | CBS_DROPDOWNLIST, WS_EX_LEFT
RTEXT "Mouse Sensitivity:", IDC_SLIDER_STATIC00, 329, 67, 100, 9, SS_RIGHT | SS_CENTERIMAGE, WS_EX_LEFT
LTEXT "100%", IDC_SLIDER_DISPLAY00, 433, 67, 30, 9, SS_LEFT | SS_CENTERIMAGE, WS_EX_LEFT
CONTROL "Sensitivity Slider", IDC_SLIDER00, TRACKBAR_CLASS, WS_TABSTOP | TBS_NOTICKS, 267, 77, 189, 11, WS_EX_LEFT
RTEXT "Mouse Acceleration:", IDC_SLIDER_STATIC01, 329, 88, 100, 9, SS_RIGHT | SS_CENTERIMAGE, WS_EX_LEFT
LTEXT "None", IDC_SLIDER_DISPLAY01, 433, 88, 30, 9, SS_LEFT | SS_CENTERIMAGE, WS_EX_LEFT
CONTROL "Acceleration Slider", IDC_SLIDER01, TRACKBAR_CLASS, WS_TABSTOP | TBS_AUTOTICKS, 267, 98, 189, 11, WS_EX_LEFT
RTEXT "Crosshair Movement:", IDC_SLIDER_STATIC02, 329, 111, 100, 9, SS_RIGHT | SS_CENTERIMAGE, WS_EX_LEFT
LTEXT "100%", IDC_SLIDER_DISPLAY02, 433, 111, 30, 9, SS_LEFT | SS_CENTERIMAGE, WS_EX_LEFT
CONTROL "Crosshair Slider", IDC_SLIDER02, TRACKBAR_CLASS, WS_TABSTOP | TBS_AUTOTICKS, 267, 120, 189, 11, WS_EX_LEFT
AUTOCHECKBOX "Reverse Mouse Pitch", IDC_INVERTPITCH, 271, 134, 86, 17, WS_TABSTOP, WS_EX_LEFT
AUTOCHECKBOX "Cursor Aiming (GE)", IDC_GECURSORAIMING, 369, 134, 83, 17, WS_TABSTOP, WS_EX_RIGHT
AUTOCHECKBOX "Crouch Toggle", IDC_CROUCHTOGGLE, 271, 150, 65, 17, WS_TABSTOP, WS_EX_LEFT
AUTOCHECKBOX "Cursor Aiming (PD)", IDC_PDCURSORAIMING, 369, 150, 83, 17, WS_TABSTOP, WS_EX_RIGHT
GROUPBOX "All Players", IDC_ALLPLAYERS, 271, 168, 181, 75, 0, WS_EX_RIGHT
LTEXT "16 x 9 Ratio Override:", IDC_RATIOSTATIC, 279, 179, 76, 9, SS_LEFT, WS_EX_LEFT
EDITTEXT IDC_RATIOWIDTH, 398, 178, 15, 12, ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER, WS_EX_LEFT
CTEXT "x", IDC_RATIOSTATICX, 417, 179, 8, 9, SS_LEFT | SS_CENTER, WS_EX_LEFT
EDITTEXT IDC_RATIOHEIGHT, 428, 178, 15, 12, ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER, WS_EX_LEFT
PUSHBUTTON "Reset FOV", IDC_RESETFOV, 278, 192, 40, 9, WS_TABSTOP, WS_EX_RIGHT
LTEXT "Vertical FOV: 60 (Hor 91)", IDC_FOV_DEGREES, 358, 192, 93, 9, SS_LEFT | SS_CENTERIMAGE | SS_NOTIFY, WS_EX_LEFT
CONTROL "Field of View Slider", IDC_FOV, TRACKBAR_CLASS, WS_TABSTOP | TBS_NOTICKS, 274, 202, 175, 14, WS_EX_LEFT
LTEXT "Default FOV", IDC_FOV_NOTE, 279, 217, 80, 8, SS_LEFT | SS_NOTIFY, WS_EX_LEFT
AUTOCHECKBOX "Show Crosshair (GE)", IDC_GESHOWCROSSHAIR, 363, 217, 81, 8, WS_TABSTOP, WS_EX_RIGHT
AUTOCHECKBOX "Bypass ViewModel Position Fix For FOV Override", IDC_BYPASSVIEWMODELFOVWEAK, 275, 229, 169, 9, WS_TABSTOP, WS_EX_RIGHT
GROUPBOX "Info", IDC_INFOBOX, 271, 245, 181, 66, NOT WS_TABSTOP, WS_EX_RIGHT
CTEXT "For multiplayer, connect multiple mice/keyboards and restart 1964, then select the device per player.\r\n\r\nIf you wish to use a USB controller, change the input plugin to N-Rage Or DirectInput.", IDC_INFO, 274, 259, 176, 41, NOT WS_GROUP | SS_CENTER, WS_EX_TRANSPARENT
PUSHBUTTON "Revert", IDC_REVERT, 298, 317, 60, 14, WS_TABSTOP, WS_EX_LEFT
PUSHBUTTON "Clear", IDC_CLEAR, 364, 317, 60, 14, WS_TABSTOP, WS_EX_LEFT
CTEXT "", IDC_PARTITION, 7, 337, 456, 2, SS_CENTER | SS_SUNKEN, WS_EX_LEFT
RTEXT "Toggle Injection", IDC_LOCK_LABEL, 17, 347, 70, 15, SS_RIGHT | SS_CENTERIMAGE, WS_EX_TRANSPARENT
PUSHBUTTON "Lock", IDC_LOCK, 97, 347, 70, 14, WS_GROUP | BS_FLAT, WS_EX_LEFT
AUTOCHECKBOX "Autolock Mouse", IDC_LOCKONFOCUS, 177, 344, 110, 8, WS_TABSTOP, WS_EX_LEFT
AUTOCHECKBOX "Unlock Mouse on Window Loss", IDC_UNLOCKONWINLOSS, 177, 355, 110, 10, WS_TABSTOP, WS_EX_LEFT
DEFPUSHBUTTON "OK", IDC_OK, 293, 347, 50, 14, 0, WS_EX_LEFT
PUSHBUTTON "Cancel", IDC_CANCEL, 353, 347, 50, 14, 0, WS_EX_LEFT
PUSHBUTTON "Help", IDC_HELPPOPUP, 413, 347, 50, 14, 0, WS_EX_LEFT
}
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
1 VERSIONINFO
FILEVERSION 2,3,0,0
PRODUCTVERSION 2,3,0,0
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_DLL
FILESUBTYPE VFT2_UNKNOWN
FILEFLAGSMASK 0
FILEFLAGS 0
{
BLOCK "StringFileInfo"
{
BLOCK "040904B0"
{
VALUE "FileDescription", "Mouse Injector for 1964"
VALUE "FileVersion", "2, 3, 0, 0"
VALUE "InternalName", "Mouse Injector"
VALUE "LegalCopyright", "Copyright (C) 2021 Carnivorous"
VALUE "OriginalFilename", "Mouse_Injector.dll"
VALUE "ProductName", "Mouse Injector for GE/PD"
VALUE "ProductVersion", "2, 3, 0, 0"
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 0x0409, 0x04B0
}
}
-538
View File
@@ -1,538 +0,0 @@
//==========================================================================
// Mouse Injector Plugin
//==========================================================================
// Copyright (C) 2016-2021 Carnivorous
// All rights reserved.
//
// Mouse Injector is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, visit http://www.gnu.org/licenses/gpl-2.0.html
//==========================================================================
// Virtual Keys, Standard Set
#define VK_LBUTTON 0x01
#define VK_RBUTTON 0x02
#define VK_CANCEL 0x03
#define VK_MBUTTON 0x04 // NOT contiguous with L & RBUTTON
#if(_WIN32_WINNT >= 0x0500)
#define VK_XBUTTON1 0x05 // NOT contiguous with L & RBUTTON
#define VK_XBUTTON2 0x06 // NOT contiguous with L & RBUTTON
#endif
// 0x07 : unassigned
#define VK_BACK 0x08
#define VK_TAB 0x09
// 0x0A - 0x0B : mouse wheel
#define VK_WHEELUP 0x0A // THERE IS NO SUCH THING AS VK_WHEELUP - I INVENTED THIS BECAUSE I'M LAZY - TERRIBLE HACK
#define VK_WHEELDOWN 0x0B // THERE IS NO SUCH THING AS VK_WHEELDOWN - I INVENTED THIS BECAUSE I'M LAZY - TERRIBLE HACK
#define VK_CLEAR 0x0C
#define VK_RETURN 0x0D
#define VK_WHEELLEFT 0x0F // THERE IS NO SUCH THING AS VK_WHEELLEFT - I INVENTED THIS BECAUSE I'M LAZY - TERRIBLE HACK
#define VK_WHEELRIGHT 0x0E // THERE IS NO SUCH THING AS VK_WHEELRIGHT - I INVENTED THIS BECAUSE I'M LAZY - TERRIBLE HACK
#define VK_SHIFT 0x10
#define VK_CONTROL 0x11
#define VK_MENU 0x12
#define VK_PAUSE 0x13
#define VK_CAPITAL 0x14
#define VK_KANA 0x15
#define VK_HANGEUL 0x15 // old name - should be here for compatibility
#define VK_HANGUL 0x15
#define VK_JUNJA 0x17
#define VK_FINAL 0x18
#define VK_HANJA 0x19
#define VK_KANJI 0x19
#define VK_ESCAPE 0x1B
#define VK_CONVERT 0x1C
#define VK_NONCONVERT 0x1D
#define VK_ACCEPT 0x1E
#define VK_MODECHANGE 0x1F
#define VK_SPACE 0x20
#define VK_PRIOR 0x21
#define VK_NEXT 0x22
#define VK_END 0x23
#define VK_HOME 0x24
#define VK_LEFT 0x25
#define VK_UP 0x26
#define VK_RIGHT 0x27
#define VK_DOWN 0x28
#define VK_SELECT 0x29
#define VK_PRINT 0x2A
#define VK_EXECUTE 0x2B
#define VK_SNAPSHOT 0x2C
#define VK_INSERT 0x2D
#define VK_DELETE 0x2E
#define VK_HELP 0x2F
// VK_0 - VK_9 are the same as ASCII '0' - '9' (0x30 - 0x39)
// 0x40 : unassigned
// VK_A - VK_Z are the same as ASCII 'A' - 'Z' (0x41 - 0x5A)
#define VK_LWIN 0x5B
#define VK_RWIN 0x5C
#define VK_APPS 0x5D
// 0x5E : reserved
#define VK_SLEEP 0x5F
#define VK_NUMPAD0 0x60
#define VK_NUMPAD1 0x61
#define VK_NUMPAD2 0x62
#define VK_NUMPAD3 0x63
#define VK_NUMPAD4 0x64
#define VK_NUMPAD5 0x65
#define VK_NUMPAD6 0x66
#define VK_NUMPAD7 0x67
#define VK_NUMPAD8 0x68
#define VK_NUMPAD9 0x69
#define VK_MULTIPLY 0x6A
#define VK_ADD 0x6B
#define VK_SEPARATOR 0x6C
#define VK_SUBTRACT 0x6D
#define VK_DECIMAL 0x6E
#define VK_DIVIDE 0x6F
#define VK_F1 0x70
#define VK_F2 0x71
#define VK_F3 0x72
#define VK_F4 0x73
#define VK_F5 0x74
#define VK_F6 0x75
#define VK_F7 0x76
#define VK_F8 0x77
#define VK_F9 0x78
#define VK_F10 0x79
#define VK_F11 0x7A
#define VK_F12 0x7B
#define VK_F13 0x7C
#define VK_F14 0x7D
#define VK_F15 0x7E
#define VK_F16 0x7F
#define VK_F17 0x80
#define VK_F18 0x81
#define VK_F19 0x82
#define VK_F20 0x83
#define VK_F21 0x84
#define VK_F22 0x85
#define VK_F23 0x86
#define VK_F24 0x87
// 0x88 - 0x8F : unassigned
#define VK_NUMLOCK 0x90
#define VK_SCROLL 0x91
// NEC PC-9800 kbd definitions
#define VK_OEM_NEC_EQUAL 0x92 // '=' key on numpad
// Fujitsu/OASYS kbd definitions
#define VK_OEM_FJ_JISHO 0x92 // 'Dictionary' key
#define VK_OEM_FJ_MASSHOU 0x93 // 'Unregister word' key
#define VK_OEM_FJ_TOUROKU 0x94 // 'Register word' key
#define VK_OEM_FJ_LOYA 0x95 // 'Left OYAYUBI' key
#define VK_OEM_FJ_ROYA 0x96 // 'Right OYAYUBI' key
// 0x97 - 0x9F : unassigned
// VK_L* & VK_R* - left and right Alt, Ctrl and Shift virtual keys.
// Used only as parameters to GetAsyncKeyState() and GetKeyState().
// No other API or message will distinguish left and right keys in this way.
#define VK_LSHIFT 0xA0
#define VK_RSHIFT 0xA1
#define VK_LCONTROL 0xA2
#define VK_RCONTROL 0xA3
#define VK_LMENU 0xA4
#define VK_RMENU 0xA5
#if(_WIN32_WINNT >= 0x0500)
#define VK_BROWSER_BACK 0xA6
#define VK_BROWSER_FORWARD 0xA7
#define VK_BROWSER_REFRESH 0xA8
#define VK_BROWSER_STOP 0xA9
#define VK_BROWSER_SEARCH 0xAA
#define VK_BROWSER_FAVORITES 0xAB
#define VK_BROWSER_HOME 0xAC
#define VK_VOLUME_MUTE 0xAD
#define VK_VOLUME_DOWN 0xAE
#define VK_VOLUME_UP 0xAF
#define VK_MEDIA_NEXT_TRACK 0xB0
#define VK_MEDIA_PREV_TRACK 0xB1
#define VK_MEDIA_STOP 0xB2
#define VK_MEDIA_PLAY_PAUSE 0xB3
#define VK_LAUNCH_MAIL 0xB4
#define VK_LAUNCH_MEDIA_SELECT 0xB5
#define VK_LAUNCH_APP1 0xB6
#define VK_LAUNCH_APP2 0xB7
#endif
// 0xB8 - 0xB9 : reserved
#define VK_OEM_1 0xBA // ';:' for US
#define VK_OEM_PLUS 0xBB // '+' any country
#define VK_OEM_COMMA 0xBC // ',' any country
#define VK_OEM_MINUS 0xBD // '-' any country
#define VK_OEM_PERIOD 0xBE // '.' any country
#define VK_OEM_2 0xBF // '/?' for US
#define VK_OEM_3 0xC0 // '`~' for US
// 0xC1 - 0xD7 : reserved
// 0xD8 - 0xDA : unassigned
#define VK_OEM_4 0xDB // '[{' for US
#define VK_OEM_5 0xDC // '\|' for US
#define VK_OEM_6 0xDD // ']}' for US
#define VK_OEM_7 0xDE // ''"' for US
#define VK_OEM_8 0xDF
// 0xE0 : reserved
// Various extended or enhanced keyboards
#define VK_OEM_AX 0xE1 // 'AX' key on Japanese AX kbd
#define VK_OEM_102 0xE2 // "<>" or "\|" on RT 102-key kbd.
#define VK_ICO_HELP 0xE3 // Help key on ICO
#define VK_ICO_00 0xE4 // 00 key on ICO
#if(WINVER >= 0x0400)
#define VK_PROCESSKEY 0xE5
#endif
#define VK_ICO_CLEAR 0xE6
#if(_WIN32_WINNT >= 0x0500)
#define VK_PACKET 0xE7
#endif
// 0xE8 : unassigned
// Nokia/Ericsson definitions
#define VK_OEM_RESET 0xE9
#define VK_OEM_JUMP 0xEA
#define VK_OEM_PA1 0xEB
#define VK_OEM_PA2 0xEC
#define VK_OEM_PA3 0xED
#define VK_OEM_WSCTRL 0xEE
#define VK_OEM_CUSEL 0xEF
#define VK_OEM_ATTN 0xF0
#define VK_OEM_FINISH 0xF1
#define VK_OEM_COPY 0xF2
#define VK_OEM_AUTO 0xF3
#define VK_OEM_ENLW 0xF4
#define VK_OEM_BACKTAB 0xF5
#define VK_ATTN 0xF6
#define VK_CRSEL 0xF7
#define VK_EXSEL 0xF8
#define VK_EREOF 0xF9
#define VK_PLAY 0xFA
#define VK_ZOOM 0xFB
#define VK_NONAME 0xFC
#define VK_PA1 0xFD
#define VK_OEM_CLEAR 0xFE
// 0xFF : reserved
struct VKeyInfo
{
unsigned int VKey;
LPCSTR VKname;
};
#define AddVKey(VK, VKName) {(VK), (VKName)}
static struct VKeyInfo vkis[] =
{
AddVKey(0x00, "None"), // THERE IS NO SUCH THING AS 0x00 - I INVENTED THIS BECAUSE I'M LAZY - TERRIBLE HACK
AddVKey(VK_LBUTTON, "Left Mouse Button"),
AddVKey(VK_RBUTTON, "Right Mouse Button"),
AddVKey(VK_CANCEL, "Control-Break"),
AddVKey(0x04, "Middle Mouse Button"),
AddVKey(0x05, "X1 Mouse Button"),
AddVKey(0x06, "X2 Mouse Button"),
AddVKey(0x07, "Undefined"),
AddVKey(VK_BACK, "Backspace"),
AddVKey(VK_TAB, "Tab"),
AddVKey(0x0A, "Mouse Wheel Up"), // THERE IS NO SUCH THING AS VK_WHEELUP - I INVENTED THIS BECAUSE I'M LAZY - TERRIBLE HACK
AddVKey(0x0B, "Mouse Wheel Down"), // THERE IS NO SUCH THING AS VK_WHEELDOWN - I INVENTED THIS BECAUSE I'M LAZY - TERRIBLE HACK
AddVKey(VK_CLEAR, "Clear"),
AddVKey(VK_RETURN, "Enter"),
AddVKey(0x0E, "Mouse Wheel Left"), // THERE IS NO SUCH THING AS VK_WHEELLEFT - I INVENTED THIS BECAUSE I'M LAZY - TERRIBLE HACK
AddVKey(0x0F, "Mouse Wheel Right"), // THERE IS NO SUCH THING AS VK_WHEELRIGHT - I INVENTED THIS BECAUSE I'M LAZY - TERRIBLE HACK
AddVKey(VK_SHIFT, "Shift"),
AddVKey(VK_CONTROL, "Control"),
AddVKey(VK_MENU, "Alt"),
AddVKey(VK_PAUSE, "Pause"),
AddVKey(VK_CAPITAL, "Caps Lock"),
AddVKey(VK_KANA, "IME Kana"), // Input Method Editor (IME) Kana mode
AddVKey(VK_HANGUL, "IME Hangul"),
AddVKey(0x16, "Undefined"),
AddVKey(VK_JUNJA, "IME Junja"),
AddVKey(VK_FINAL, "IME final"),
AddVKey(VK_HANJA, "IME Hanja"),
AddVKey(VK_KANJI, "IME Kanji"),
AddVKey(0x1A, "Undefined"),
AddVKey(VK_ESCAPE, "Escape"),
AddVKey(VK_CONVERT, "IME Convert"),
AddVKey(VK_NONCONVERT, "IME Non-Convert"),
AddVKey(VK_ACCEPT, "IME Accept"),
AddVKey(VK_MODECHANGE, "IME Mode Change"),
AddVKey(VK_SPACE, "Spacebar"),
AddVKey(VK_PRIOR, "Page Up"),
AddVKey(VK_NEXT, "Page Down"),
AddVKey(VK_END, "End"),
AddVKey(VK_HOME, "Home"),
AddVKey(VK_LEFT, "Left Arrow"),
AddVKey(VK_UP, "Up Arrow"),
AddVKey(VK_RIGHT, "Right Arrow"),
AddVKey(VK_DOWN, "Down Arrow"),
AddVKey(VK_SELECT, "Select"),
AddVKey(VK_PRINT, "Print"),
AddVKey(VK_EXECUTE, "Execute"),
AddVKey(VK_SNAPSHOT, "Print Screen"),
AddVKey(VK_INSERT, "Insert"),
AddVKey(VK_DELETE, "Delete"),
AddVKey(VK_HELP, "Help"),
AddVKey(0x30, "0"),
AddVKey(0x31, "1"),
AddVKey(0x32, "2"),
AddVKey(0x33, "3"),
AddVKey(0x34, "4"),
AddVKey(0x35, "5"),
AddVKey(0x36, "6"),
AddVKey(0x37, "7"),
AddVKey(0x38, "8"),
AddVKey(0x39, "9"),
AddVKey(0x3A, "Undefined"),
AddVKey(0x3B, "Undefined"),
AddVKey(0x3C, "Undefined"),
AddVKey(0x3D, "Undefined"),
AddVKey(0x3E, "Undefined"),
AddVKey(0x3F, "Undefined"),
AddVKey(0x40, "Undefined"),
AddVKey(0x41, "A"),
AddVKey(0x42, "B"),
AddVKey(0x43, "C"),
AddVKey(0x44, "D"),
AddVKey(0x45, "E"),
AddVKey(0x46, "F"),
AddVKey(0x47, "G"),
AddVKey(0x48, "H"),
AddVKey(0x49, "I"),
AddVKey(0x4A, "J"),
AddVKey(0x4B, "K"),
AddVKey(0x4C, "L"),
AddVKey(0x4D, "M"),
AddVKey(0x4E, "N"),
AddVKey(0x4F, "O"),
AddVKey(0x50, "P"),
AddVKey(0x51, "Q"),
AddVKey(0x52, "R"),
AddVKey(0x53, "S"),
AddVKey(0x54, "T"),
AddVKey(0x55, "U"),
AddVKey(0x56, "V"),
AddVKey(0x57, "W"),
AddVKey(0x58, "X"),
AddVKey(0x59, "Y"),
AddVKey(0x5A, "Z"),
AddVKey(VK_LWIN, "Left Windows"), // Left Windows key (Microsoft Natural keyboard)
AddVKey(VK_RWIN, "Right Windows"), // Right Windows key (Natural keyboard)
AddVKey(VK_APPS, "App"), // Applications key (Natural keyboard)
AddVKey(0x5E, "Reserved"),
AddVKey(VK_SLEEP, "Sleep"),
AddVKey(VK_NUMPAD0, "Numpad #0"),
AddVKey(VK_NUMPAD1, "Numpad #1"),
AddVKey(VK_NUMPAD2, "Numpad #2"),
AddVKey(VK_NUMPAD3, "Numpad #3"),
AddVKey(VK_NUMPAD4, "Numpad #4"),
AddVKey(VK_NUMPAD5, "Numpad #5"),
AddVKey(VK_NUMPAD6, "Numpad #6"),
AddVKey(VK_NUMPAD7, "Numpad #7"),
AddVKey(VK_NUMPAD8, "Numpad #8"),
AddVKey(VK_NUMPAD9, "Numpad #9"),
AddVKey(VK_MULTIPLY, "Numpad *"),
AddVKey(VK_ADD, "Numpad +"),
AddVKey(VK_SEPARATOR, "Separator"),
AddVKey(VK_SUBTRACT, "Numpad -"),
AddVKey(VK_DECIMAL, "Numpad ."),
AddVKey(VK_DIVIDE, "Numpad /"),
AddVKey(VK_F1, "F1"),
AddVKey(VK_F2, "F2"),
AddVKey(VK_F3, "F3"),
AddVKey(VK_F4, "F4"),
AddVKey(VK_F5, "F5"),
AddVKey(VK_F6, "F6"),
AddVKey(VK_F7, "F7"),
AddVKey(VK_F8, "F8"),
AddVKey(VK_F9, "F9"),
AddVKey(VK_F10, "F10"),
AddVKey(VK_F11, "F11"),
AddVKey(VK_F12, "F12"),
AddVKey(VK_F13, "F13"),
AddVKey(VK_F14, "F14"),
AddVKey(VK_F15, "F15"),
AddVKey(VK_F16, "F16"),
AddVKey(VK_F17, "F17"),
AddVKey(VK_F18, "F18"),
AddVKey(VK_F19, "F19"),
AddVKey(VK_F20, "F20"),
AddVKey(VK_F21, "F21"),
AddVKey(VK_F22, "F22"),
AddVKey(VK_F23, "F23"),
AddVKey(VK_F24, "F24"),
AddVKey(0x88, "Unassigned"),
AddVKey(0x89, "Unassigned"),
AddVKey(0x8A, "Unassigned"),
AddVKey(0x8B, "Unassigned"),
AddVKey(0x8C, "Unassigned"),
AddVKey(0x8D, "Unassigned"),
AddVKey(0x8E, "Unassigned"),
AddVKey(0x8F, "Unassigned"),
AddVKey(VK_NUMLOCK, "Num Lock"),
AddVKey(VK_SCROLL, "Scroll Lock"),
AddVKey(0x92, "OEM specific"),
AddVKey(0x93, "OEM specific"),
AddVKey(0x94, "OEM specific"),
AddVKey(0x95, "OEM specific"),
AddVKey(0x96, "OEM specific"),
AddVKey(0x97, "Unassigned"),
AddVKey(0x98, "Unassigned"),
AddVKey(0x99, "Unassigned"),
AddVKey(0x9A, "Unassigned"),
AddVKey(0x9B, "Unassigned"),
AddVKey(0x9C, "Unassigned"),
AddVKey(0x9D, "Unassigned"),
AddVKey(0x9E, "Unassigned"),
AddVKey(0x9F, "Unassigned"),
AddVKey(VK_LSHIFT, "Left Shift"),
AddVKey(VK_RSHIFT, "Right Shift"),
AddVKey(VK_LCONTROL, "Left Control"),
AddVKey(VK_RCONTROL, "Right Control"),
AddVKey(VK_LMENU, "Left Alt"),
AddVKey(VK_RMENU, "Right Alt"),
AddVKey(0xA6, "Browser Back"), // Windows 2000/XP: Browser Back key
AddVKey(0xA7, "Browser Forward"), // Windows 2000/XP: Browser Forward key
AddVKey(0xA8, "Browser Refresh"), // Windows 2000/XP: Browser Refresh key
AddVKey(0xA9, "Browser Stop"), // Windows 2000/XP: Browser Stop key
AddVKey(0xAA, "Browser Search"), // Windows 2000/XP: Browser Search key
AddVKey(0xAB, "Browser Favorites"), // Windows 2000/XP: Browser Favorites key
AddVKey(0xAC, "Browser Start/Home"), // Windows 2000/XP: Browser Start and Home key
AddVKey(0xAD, "Volume Mute"), // Windows 2000/XP: Volume Mute key
AddVKey(0xAE, "Volume Down"), // Windows 2000/XP: Volume Down key
AddVKey(0xAF, "Volume Up"), // Windows 2000/XP: Volume Up key
AddVKey(0xB0, "Next Track"), // Windows 2000/XP: Next Track key
AddVKey(0xB1, "Previous Track"), // Windows 2000/XP: Previous Track key
AddVKey(0xB2, "Stop Track"), // Windows 2000/XP: Stop Media key
AddVKey(0xB3, "Play/Pause Track"), // Windows 2000/XP: Play/Pause Media key
AddVKey(0xB4, "E-Mail"), // Windows 2000/XP: Start Mail key
AddVKey(0xB5, "Select Track"), // Windows 2000/XP: Select Media key
AddVKey(0xB6, "Start App 1"), // Windows 2000/XP: Start Application 1 key
AddVKey(0xB7, "Start App 2"), // Windows 2000/XP: Start Application 2 key
AddVKey(0xB8, "Reserved"),
AddVKey(0xB9, "Reserved"),
AddVKey(VK_OEM_1, ":"), // Used for miscellaneous characters; it can vary by keyboard." "Windows 2000/XP: For the US standard keyboard, the \';:\' key
AddVKey(VK_OEM_PLUS, "+"), // Windows 2000/XP: For any country/region, the \'+\' key
AddVKey(VK_OEM_COMMA, ","), // Windows 2000/XP: For any country/region, the \',\' key
AddVKey(VK_OEM_MINUS, "-"), // Windows 2000/XP: For any country/region, the \'-\' key
AddVKey(VK_OEM_PERIOD, "."), // Windows 2000/XP: For any country/region, the \'.\' key
AddVKey(VK_OEM_2, "?"), // Used for miscellaneous characters; it can vary by keyboard." "Windows 2000/XP: For the US standard keyboard, the \'/?\' key
AddVKey(VK_OEM_3, "~"), // Used for miscellaneous characters; it can vary by keyboard." "Windows 2000/XP: For the US standard keyboard, the \'`~\' key
AddVKey(0xC1, "Reserved"),
AddVKey(0xC2, "Reserved"),
AddVKey(0xC3, "Reserved"),
AddVKey(0xC4, "Reserved"),
AddVKey(0xC5, "Reserved"),
AddVKey(0xC6, "Reserved"),
AddVKey(0xC7, "Reserved"),
AddVKey(0xC8, "Reserved"),
AddVKey(0xC9, "Reserved"),
AddVKey(0xCA, "Reserved"),
AddVKey(0xCB, "Reserved"),
AddVKey(0xCC, "Reserved"),
AddVKey(0xCD, "Reserved"),
AddVKey(0xCE, "Reserved"),
AddVKey(0xCF, "Reserved"),
AddVKey(0xD0, "Reserved"),
AddVKey(0xD1, "Reserved"),
AddVKey(0xD2, "Reserved"),
AddVKey(0xD3, "Reserved"),
AddVKey(0xD4, "Reserved"),
AddVKey(0xD5, "Reserved"),
AddVKey(0xD6, "Reserved"),
AddVKey(0xD7, "Reserved"),
AddVKey(0xD8, "Unassigned"),
AddVKey(0xD9, "Unassigned"),
AddVKey(0xDA, "Unassigned"),
AddVKey(VK_OEM_4, "["), // Used for miscellaneous characters; it can vary by keyboard." "Windows 2000/XP: For the US standard keyboard, the \'[{\' key
AddVKey(VK_OEM_5, "\\"), // Used for miscellaneous characters; it can vary by keyboard." "Windows 2000/XP: For the US standard keyboard, the \'\\|\' key
AddVKey(VK_OEM_6, "]"), // Used for miscellaneous characters; it can vary by keyboard." "Windows 2000/XP: For the US standard keyboard, the \']}\' key
AddVKey(VK_OEM_7, "'"), // Used for miscellaneous characters; it can vary by keyboard." "Windows 2000/XP: For the US standard keyboard, the \'single-quote/double-quote\' key
AddVKey(VK_OEM_8, "OEM Misc"), // Used for miscellaneous characters; it can vary by keyboard.
AddVKey(0xE0, "Reserved"),
AddVKey(0xE1, "OEM Specific"),
AddVKey(VK_OEM_102, "Angle Bracket"), // Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard
AddVKey(0xE3, "OEM Specific"),
AddVKey(0xE4, "OEM Specific"),
AddVKey(VK_PROCESSKEY, "IME Process"), // Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key
AddVKey(0xE6, "OEM Specific"),
AddVKey(0xE7, "Packet"), // Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KEYUP
AddVKey(0xE8, "Unassigned"),
AddVKey(0xE9, "OEM Specific"),
AddVKey(0xEA, "OEM Specific"),
AddVKey(0xEB, "OEM Specific"),
AddVKey(0xEC, "OEM Specific"),
AddVKey(0xED, "OEM Specific"),
AddVKey(0xEF, "OEM Specific"),
AddVKey(0xF0, "OEM Specific"),
AddVKey(0xF1, "OEM Specific"),
AddVKey(0xF2, "OEM Specific"),
AddVKey(0xF3, "OEM Specific"),
AddVKey(0xF4, "OEM Specific"),
AddVKey(0xF5, "OEM Specific"),
AddVKey(VK_ATTN, "Attn"),
AddVKey(VK_CRSEL, "CrSel"),
AddVKey(VK_EXSEL, "ExSel"),
AddVKey(VK_EREOF, "Erase"),
AddVKey(VK_PLAY, "Play"),
AddVKey(VK_ZOOM, "Zoom"),
AddVKey(VK_NONAME, "No Name"),
AddVKey(VK_PA1, "Pa1"),
AddVKey(VK_OEM_CLEAR, "Clear"),
AddVKey(0xFF, "Invalid Key")
};
static LPCSTR GetKeyName(unsigned int VKey)
{
for(unsigned int i = 0; i < ARRAY_SIZE(vkis); i++)
{
if(VKey == vkis[i].VKey)
return vkis[i].VKname;
}
return vkis[0xFF].VKname; // return "Invalid Key"
}
-254
View File
@@ -1,254 +0,0 @@
pass_count=253 enum_count=253
0 GotoNext
1 GotoFirst
2 Label
3 Yield
4 EndList
5 SetChrAiList
6 SetReturnAiList
7 Return
8 Stop
9 Kneel
10 PlayAnimation
11 IFPlayingAnimation
12 PointAtBond
13 LookSurprised
14 TRYSidestepping
15 TRYSideHopping
16 TRYSideRunning
17 TRYFiringWalk
18 TRYFiringRun
19 TRYFiringRoll
20 TRYFireOrAimAtTarget
21 TRYFireOrAimAtTargetKneel
22 TRYFireOrAimAtTargetUpdate
23 TRYFacingTarget
24 HitChrWithItem
25 ChrHitChr
26 TRYThrowingGrenade
27 TRYDroppingItem
28 RunToPad
29 RunToPadPreset
30 WalkToPad
31 SprintToPad
32 StartPatrol
33 Surrender
34 RemoveMe
35 ChrRemoveInstant
36 TRYTriggeringAlarmAtPad
37 AlarmOn
38 AlarmOff
39 TRYRunFromBond
40 TRYRunToBond
41 TRYWalkToBond
42 TRYSprintToBond
43 TRYFindCover
44 TRYRunToChr
45 TRYWalkToChr
46 TRYSprintToChr
47 IFImOnPatrolOrStopped
48 IFChrDyingOrDead
49 IFChrDoesNotExist
50 IFISeeBond
51 SetNewRandom
52 IFRandomLessThan
53 IFRandomGreaterThan
54 IFICanHearAlarm
55 IFAlarmIsOn
56 IFGasIsLeaking
57 IFIHeardBond
58 IFISeeSomeoneShot
59 IFISeeSomeoneDie
60 IFICouldSeeBond
61 IFICouldSeeBondsStan
62 IFIWasShotRecently
63 IFIHeardBondRecently
64 IFImInRoomWithChr
65 IFIveNotBeenSeen
66 IFImOnScreen
67 IFMyRoomIsOnScreen
68 IFRoomWithPadIsOnScreen
69 IFImTargetedByBond
70 IFBondMissedMe
71 IFMyAngleToBondLessThan
72 IFMyAngleToBondGreaterThan
73 IFMyAngleFromBondLessThan
74 IFMyAngleFromBondGreaterThan
75 IFMyDistanceToBondLessThanDecimeter
76 IFMyDistanceToBondGreaterThanDecimeter
77 IFChrDistanceToPadLessThanDecimeter
78 IFChrDistanceToPadGreaterThanDecimeter
79 IFMyDistanceToChrLessThanDecimeter
80 IFMyDistanceToChrGreaterThanDecimeter
81 TRYSettingMyPresetToChrWithinDistanceDecimeter
82 IFBondDistanceToPadLessThanDecimeter
83 IFBondDistanceToPadGreaterThanDecimeter
84 IFChrInRoomWithPad
85 IFBondInRoomWithPad
86 IFBondCollectedObject
87 IFKeyDropped
88 IFItemIsAttachedToObject
89 IFBondHasItemEquipped
90 IFObjectExists
91 IFObjectNotDestroyed
92 IFObjectWasActivated
93 IFBondUsedGadgetOnObject
94 ActivateObject
95 DestroyObject
96 DropObject
97 ChrDropAllConcealedItems
98 ChrDropAllHeldItems
99 BondCollectObject
100 ChrEquipObject
101 MoveObject
102 DoorOpen
103 DoorClose
104 IFDoorStateEqual
105 IFDoorHasBeenOpenedBefore
106 DoorSetLock
107 DoorUnsetLock
108 IFDoorLockEqual
109 IFObjectiveNumComplete
110 TRYUnknown6e
111 TRYUnknown6f
112 IFGameDifficultyLessThan
113 IFGameDifficultyGreaterThan
114 IFMissionTimeLessThan
115 IFMissionTimeGreaterThan
116 IFSystemPowerTimeLessThan
117 IFSystemPowerTimeGreaterThan
118 IFLevelIdLessThan
119 IFLevelIdGreaterThan
120 IFMyNumArghsLessThan
121 IFMyNumArghsGreaterThan
122 IFMyNumCloseArghsLessThan
123 IFMyNumCloseArghsGreaterThan
124 IFChrHealthLessThan
125 IFChrHealthGreaterThan
126 IFChrWasDamagedSinceLastCheck
127 IFBondHealthLessThan
128 IFBondHealthGreaterThan
129 SetMyMorale
130 AddToMyMorale
131 SubtractFromMyMorale
132 IFMyMoraleLessThan
133 IFMyMoraleLessThanRandom
134 SetMyAlertness
135 AddToMyAlertness
136 SubtractFromMyAlertness
137 IFMyAlertnessLessThan
138 IFMyAlertnessLessThanRandom
139 SetMyHearingScale
140 SetMyVisionRange
141 SetMyGrenadeProbability
142 SetMyChrNum
143 SetMyHealthTotal
144 SetMyArmour
145 SetMySpeedRating
146 SetMyArghRating
147 SetMyAccuracyRating
148 SetMyFlags2
149 UnsetMyFlags2
150 IFMyFlags2Has
151 SetChrBitfield
152 UnsetChrBitfield
153 IFChrBitfieldHas
154 SetObjectiveBitfield
155 UnsetObjectiveBitfield
156 IFObjectiveBitfieldHas
157 SetMychrflags
158 UnsetMychrflags
159 IFMychrflagsHas
160 SetChrchrflags
161 UnsetChrchrflags
162 IFChrchrflagsHas
163 SetObjectFlags
164 UnsetObjectFlags
165 IFObjectFlagsHas
166 SetObjectFlags2
167 UnsetObjectFlags2
168 IFObjectFlags2Has
169 SetMyChrPreset
170 SetChrChrPreset
171 SetMyPadPreset
172 SetChrPadPreset
173 PRINT
174 MyTimerStart
175 MyTimerReset
176 MyTimerPause
177 MyTimerResume
178 IFMyTimerIsNotRunning
179 IFMyTimerLessThanTicks
180 IFMyTimerGreaterThanTicks
181 HudCountdownShow
182 HudCountdownHide
183 HudCountdownSet
184 HudCountdownStop
185 HudCountdownStart
186 IFHudCountdownIsNotRunning
187 IFHudCountdownLessThan
188 IFHudCountdownGreaterThan
189 TRYSpawningChrAtPad
190 TRYSpawningChrNextToChr
191 TRYGiveMeItem
192 TRYGiveMeHat
193 TRYCloningChr
194 TextPrintBottom
195 TextPrintTop
196 SfxPlay
197 SfxEmitFromObject
198 SfxEmitFromPad
199 SfxSetChannelVolume
200 SfxFadeChannelVolume
201 SfxStopChannel
202 IFSfxChannelVolumeLessThan
203 VehicleStartPath
204 VehicleSpeed
205 AircraftRotorSpeed
206 IFCameraIsInIntro
207 IFCameraIsInBondSwirl
208 TvChangeScreenBank
209 IFBondInTank
210 EndLevel
211 CameraReturnToBond
212 CameraLookAtBondFromPad
213 CameraSwitch
214 IFBondYPosLessThan
215 BondDisableControl
216 BondEnableControl
217 TRYTeleportingChrToPad
218 ScreenFadeToBlack
219 ScreenFadeFromBlack
220 IFScreenFadeCompleted
221 HideAllChrs
222 ShowAllChrs
223 DoorOpenInstant
224 ChrRemoveItemInHand
225 IfNumberOfActivePlayersLessThan
226 IFBondItemTotalAmmoLessThan
227 BondEquipItem
228 BondEquipItemCinema
229 BondSetLockedVelocity
230 IFObjectInRoomWithPad
231 IFImFiringAndLockedForward
232 IFImFiring
233 SwitchSky
234 TriggerFadeAndExitLevelOnButtonPress
235 IFBondIsDead
236 BondDisableDamageAndPickups
237 BondHideWeapons
238 CameraOrbitPad
239 CreditsRoll
240 IFCreditsHasCompleted
241 IFObjectiveAllCompleted
242 IFFolderActorIsEqual
243 IFBondDamageAndPickupsDisabled
244 MusicPlaySlot
245 MusicStopSlot
246 TriggerExplosionsAroundBond
247 IFKilledCiviliansGreaterThan
248 IFChrWasShotSinceLastCheck
249 BondKilledInAction
250 RaiseArms
251 GasLeakAndFadeFog
252 ObjectRocketLaunch
-109
View File
@@ -1,109 +0,0 @@
== census (kind, format) -> count ==
('NONZLIB', 'I4'): 363
('NONZLIB', 'I8'): 231
('NONZLIB', 'IA16'): 1
('NONZLIB', 'IA4'): 74
('NONZLIB', 'IA8'): 192
('NONZLIB', 'RGB15'): 14
('NONZLIB', 'RGBA16'): 19
('NONZLIB', 'RGBA32'): 60
('ZLIB', 'IA16_CI4'): 15
('ZLIB', 'IA16_CI8'): 91
('ZLIB', 'RGBA16_CI4'): 83
('ZLIB', 'RGBA16_CI8'): 1555
== non-zlib WIDE-pixel images: 94 ==
texnum= 0 IMAGE_COPYICON RGBA32 comp=7 32x28 lod=0
texnum= 2 IMAGE_DELICON RGBA32 comp=8 32x28 lod=0
texnum= 437 _image437_ID RGBA32 comp=8 32x16 lod=6
texnum= 439 _image439_ID RGBA32 comp=8 32x16 lod=6
texnum= 884 _image884_ID RGBA32 comp=4 32x32 lod=0
texnum=1198 _image1198_ID RGBA16 comp=6 64x17 lod=6
texnum=1199 _image1199_ID RGBA16 comp=6 64x17 lod=6
texnum=1200 _image1200_ID RGBA16 comp=6 64x17 lod=6
texnum=1201 _image1201_ID RGBA16 comp=6 64x17 lod=6
texnum=2085 IMAGE_FIRE_0 RGBA16 comp=5 14x14 lod=0
texnum=2087 IMAGE_FIRE_1 RGBA16 comp=8 14x14 lod=0
texnum=2089 IMAGE_FIRE_2 RGBA16 comp=4 14x14 lod=0
texnum=2091 IMAGE_FIRE_3 RGBA16 comp=8 14x14 lod=0
texnum=2093 IMAGE_FIRE_4 RGBA16 comp=8 14x14 lod=0
texnum=2095 IMAGE_FIRE_5 RGBA16 comp=7 14x14 lod=0
texnum=2097 IMAGE_FIRE_6 RGBA16 comp=7 14x14 lod=0
texnum=2099 IMAGE_FIRE_7 RGBA16 comp=4 14x14 lod=0
texnum=2101 IMAGE_FIRE_8 RGBA16 comp=4 14x14 lod=0
texnum=2103 IMAGE_FIRE_9 RGBA16 comp=8 14x14 lod=0
texnum=2105 IMAGE_FIRE_10 RGBA16 comp=8 14x14 lod=0
texnum=2107 IMAGE_FIRE_11 RGBA16 comp=4 14x14 lod=0
texnum=2109 IMAGE_FIRE_12 RGBA16 comp=8 14x14 lod=0
texnum=2111 IMAGE_FIRE_13 RGBA16 comp=8 14x14 lod=0
texnum=2113 IMAGE_FIRE_14 RGBA16 comp=8 14x14 lod=0
texnum=2114 _image2114_ID RGBA32 comp=4 32x32 lod=0
texnum=2115 _image2115_ID RGBA32 comp=4 32x32 lod=0
texnum=2116 _image2116_ID RGBA32 comp=4 32x32 lod=0
texnum=2117 _image2117_ID RGBA32 comp=4 32x32 lod=0
texnum=2119 _image2119_ID RGBA32 comp=4 32x32 lod=0
texnum=2120 _image2120_ID RGBA32 comp=4 32x32 lod=0
texnum=2121 _image2121_ID RGBA32 comp=4 32x32 lod=0
texnum=2122 _image2122_ID RGBA32 comp=4 32x32 lod=0
texnum=2123 _image2123_ID RGBA32 comp=4 32x32 lod=0
texnum=2124 _image2124_ID RGBA32 comp=4 32x32 lod=0
texnum=2125 _image2125_ID RGBA32 comp=4 32x32 lod=0
texnum=2126 _image2126_ID RGBA32 comp=4 32x32 lod=0
texnum=2127 _image2127_ID RGBA32 comp=4 32x32 lod=0
texnum=2128 IMAGE_FLAREORANGELINE RGBA32 comp=4 16x32 lod=6
texnum=2134 IMAGE_FLAREBLUEROUND RGBA32 comp=8 32x32 lod=0
texnum=2135 IMAGE_FLAREBLUELINE RGBA32 comp=8 16x32 lod=6
texnum=2137 _image2137_ID RGBA32 comp=4 32x32 lod=0
texnum=2138 _image2138_ID RGBA32 comp=4 32x32 lod=0
texnum=2139 _image2139_ID RGBA32 comp=4 32x32 lod=0
texnum=2140 _image2140_ID RGBA32 comp=4 32x32 lod=0
texnum=2141 _image2141_ID RGBA32 comp=4 32x32 lod=0
texnum=2142 _image2142_ID RGBA32 comp=4 32x32 lod=0
texnum=2143 _image2143_ID RGBA32 comp=4 32x32 lod=0
texnum=2144 _image2144_ID RGBA32 comp=4 32x32 lod=0
texnum=2145 _image2145_ID RGBA32 comp=8 32x32 lod=0
texnum=2146 _image2146_ID RGBA32 comp=4 32x32 lod=0
texnum=2147 _image2147_ID RGBA32 comp=4 32x32 lod=0
texnum=2148 _image2148_ID RGBA32 comp=4 32x32 lod=0
texnum=2149 _image2149_ID RGBA32 comp=4 32x32 lod=0
texnum=2150 _image2150_ID RGBA32 comp=4 32x32 lod=0
texnum=2151 _image2151_ID RGBA32 comp=4 32x32 lod=0
texnum=2152 _image2152_ID RGBA32 comp=4 32x32 lod=0
texnum=2153 _image2153_ID RGBA32 comp=4 32x32 lod=0
texnum=2154 _image2154_ID RGBA32 comp=4 32x32 lod=0
texnum=2155 _image2155_ID RGBA32 comp=4 32x32 lod=0
texnum=2156 _image2156_ID RGBA32 comp=4 32x32 lod=0
texnum=2157 _image2157_ID RGBA32 comp=4 32x32 lod=0
texnum=2158 _image2158_ID RGBA32 comp=4 32x32 lod=0
texnum=2159 _image2159_ID RGBA32 comp=4 32x32 lod=0
texnum=2160 _image2160_ID RGBA32 comp=4 32x32 lod=0
texnum=2161 IMAGE_ROCKETAMMO RGBA32 comp=4 7x22 lod=0
texnum=2162 IMAGE_PLAINMINEAMMO RGBA32 comp=4 14x14 lod=0
texnum=2163 IMAGE_GRENADEAMMO RGBA32 comp=4 14x18 lod=0
texnum=2164 IMAGE_MAGAMMO RGBA32 comp=7 5x15 lod=0
texnum=2165 IMAGE_GLAMMO RGBA32 comp=4 8x21 lod=0
texnum=2166 IMAGE_KNIFEAMMO RGBA32 comp=4 6x24 lod=0
texnum=2167 IMAGE_SHOTAMMO RGBA32 comp=4 6x20 lod=0
texnum=2231 IMAGE_9MMAMMO RGBA32 comp=4 5x12 lod=0
texnum=2232 IMAGE_RIFLEAMMO RGBA32 comp=4 5x28 lod=0
texnum=2233 IMAGE_GGAMMO RGBA32 comp=4 5x12 lod=0
texnum=2234 IMAGE_MINEAMMO RGBA32 comp=4 14x14 lod=0
texnum=2235 IMAGE_PROXAMMO RGBA32 comp=4 14x14 lod=0
texnum=2236 IMAGE_CROSSHAIR1 RGBA32 comp=4 32x32 lod=0
texnum=2237 IMAGE_CROSSHAIR2 RGBA32 comp=7 32x32 lod=0
texnum=2238 IMAGE_TIMEAMMO RGBA32 comp=4 14x14 lod=0
texnum=2430 _image2430_ID IA16 comp=4 64x32 lod=1
texnum=2510 _image2510_ID RGB15 comp=7 128x12 lod=2
texnum=2511 _image2511_ID RGB15 comp=8 128x12 lod=2
texnum=2512 _image2512_ID RGB15 comp=8 128x12 lod=2
texnum=2513 _image2513_ID RGB15 comp=6 128x12 lod=2
texnum=2514 _image2514_ID RGB15 comp=6 128x12 lod=2
texnum=2515 _image2515_ID RGB15 comp=6 128x12 lod=2
texnum=2516 _image2516_ID RGB15 comp=8 128x12 lod=2
texnum=2517 _image2517_ID RGB15 comp=8 128x12 lod=2
texnum=2518 _image2518_ID RGB15 comp=8 128x12 lod=2
texnum=2519 _image2519_ID RGB15 comp=8 128x12 lod=2
texnum=2520 _image2520_ID RGB15 comp=8 128x12 lod=2
texnum=2521 _image2521_ID RGB15 comp=8 128x12 lod=3
texnum=2522 _image2522_ID RGB15 comp=8 128x12 lod=3
texnum=2523 _image2523_ID RGB15 comp=8 128x12 lod=3
-136
View File
@@ -1,136 +0,0 @@
#!/usr/bin/env python3
"""D219 offline probe: parse the non-zlib/zlib texture bitstream headers
straight out of the ROM images segment, replicating texLoad/texInflateNonZlib
header reads (src/game/image.c) so we can compare TEXCOMPMETHOD/TEXFORMAT for
IMAGE_FIRE_N vs muzzle-flash/ammo/flare/impact siblings WITHOUT running the game.
ROM: data/ge007.ntsc-final.z64
Images segment cart start 0x108F7DF0 (port/src/romassets_u.s) -> file offset 0x8F7DF0.
Offsets are cumulative sizes from assets/images.def (image_entries_load, no align).
"""
import re, sys
SEG = 0x8F7DF0
ROM = open('data/ge007.ntsc-final.z64','rb').read()
# ---- enum name -> index from image_externs.h ----
enummap = {}
_in_enum = False
_v = 0
for line in open('assets/image_externs.h', encoding='utf-8', errors='replace'):
if 'typedef enum IMAGEIDS' in line:
_in_enum = True; continue
if _in_enum and line.strip().startswith('}'):
break
m = re.match(r'\s*([A-Za-z_][A-Za-z0-9_]*)\s*,?\s*(//.*)?$', line)
if m and not line.strip().startswith('//'):
enummap[m.group(1)] = _v; _v += 1
# ---- parse images.def: field1 is a bare index or an enum name minus IMAGE_ ----
entries = []
for line in open('assets/images.def', encoding='utf-8', errors='replace'):
m = re.match(r'\s*IMAGE\(\s*([A-Za-z0-9_]+)\s*,\s*(0x[0-9A-Fa-f]+|\d+)\s*,', line)
if not m: continue
f1, sz = m.group(1), int(m.group(2), 0)
if f1.isdigit():
idx = int(f1); name = f"_image{idx}_ID"
else:
key = 'IMAGE_' + f1 if not f1.startswith('IMAGE_') else f1
idx = enummap.get(key)
name = key
if idx is None:
# named in images.def but left _imageN_ID in the decomp enum --
# trust position
idx = len(entries)
print(f"# note: {key} not in enum, using positional index {idx}", file=sys.stderr)
assert idx == len(entries), f"images.def out of order at {name} ({idx} vs {len(entries)})"
entries.append((name, sz))
print(f"# {len(entries)} image entries", file=sys.stderr)
# cumulative offsets (image_entries_load)
offs = []
o = 0
for name, sz in entries:
offs.append(o)
o += sz
total = o
print(f"# images segment total size per g_Textures: {total:#x} (segment room to 0xC00000-0x8F7DF0 = {0xC00000-SEG:#x})", file=sys.stderr)
class Bits:
def __init__(self, buf, pos):
self.buf = buf; self.pos = pos; self.bit = 0
def read(self, n):
v = 0
for _ in range(n):
byte = self.buf[self.pos]
v = (v << 1) | ((byte >> (7 - self.bit)) & 1)
self.bit += 1
if self.bit == 8:
self.bit = 0; self.pos += 1
return v
NAMES = {n:i for i,(n,_) in enumerate(entries)}
def dump(i, name):
off = offs[i]
base = SEG + off
b0 = ROM[base]
u, z, lod = (b0>>7)&1, (b0>>6)&1, b0 & 0x3f
out = [f"texnum={i:4d} {name:28s} off={off:#08x} byte0={b0:#04x} u={u} z={z} lod={lod}"]
if z:
# zlib path: format(8), numcolours(8)+1, palette... then per-image w/h
b = Bits(ROM, base+1)
fmt = b.read(8); nc = b.read(8)+1
pal = [b.read(16) for _ in range(nc)]
out.append(f" ZLIB format={fmt} numcolours={nc} pal0={pal[0]:#05x}")
w = b.read(8); h = b.read(8)
out.append(f" image0 {w}x{h} (zlib payload follows -- indices only)")
else:
b = Bits(ROM, base+1)
fmt = b.read(4); w = b.read(8); h = b.read(8); cm = b.read(4)
out.append(f" NONZLIB format={fmt} width={w} height={h} compmethod={cm}")
return ' '.join(out)
FMT = {0:'RGBA32',1:'RGBA16',2:'RGB24',3:'RGB15',4:'IA16',5:'IA8',6:'IA4',7:'I8',8:'I4',9:'RGBA16_CI8',10:'RGBA16_CI4',11:'IA16_CI8',12:'IA16_CI4'}
CM = {0:'UNCOMPRESSED0',1:'UNCOMPRESSED1',2:'HUFFMAN',3:'HUFFMANPERHCHANNEL',4:'RLE',5:'LOOKUP',6:'HUFFMANLOOKUP',7:'RLELOOKUP',8:'HUFFMANBLUR',9:'RLEBLUR'}
def dump2(i, name):
off = offs[i]
base = SEG + off
b0 = ROM[base]
z = (b0>>6)&1; lod = b0 & 0x3f
line = f"texnum={i:4d} {name:28s} off={off:#08x} byte0={b0:#04x} z={z} lod={lod}"
if z:
b = Bits(ROM, base+1)
fmt = b.read(8); nc = b.read(8)+1
pal = [b.read(16) for _ in range(nc)]
w = b.read(8); h = b.read(8)
line += f" ZLIB fmt={FMT.get(fmt,fmt)}({fmt}) ncols={nc} pal0={pal[0]:#05x} img0={w}x{h}"
else:
b = Bits(ROM, base+1)
fmt = b.read(4); w = b.read(8); h = b.read(8); cm = b.read(4)
line += f" NONZLIB fmt={FMT.get(fmt,fmt)}({fmt}) {w}x{h} comp={CM.get(cm,cm)}({cm})"
return line
targets = []
# fire + smoke particle range
for i in range(2084, 2116):
targets.append(i)
# flares
for n in ['IMAGE_FLAREORANGELINE','IMAGE_FLAREBLUEROUND','IMAGE_FLAREBLUELINE','IMAGE_FLAREWHITEROUND']:
targets.append(NAMES[n])
# ammo HUD icons
for n in ['IMAGE_ROCKETAMMO','IMAGE_PLAINMINEAMMO','IMAGE_GRENADEAMMO','IMAGE_MAGAMMO','IMAGE_GLAMMO','IMAGE_KNIFEAMMO','IMAGE_SHOTAMMO']:
targets.append(NAMES[n])
# impact sprites
for n in ['IMAGE_IMPACT1','IMAGE_IMPACT2','IMAGE_IMPACT3','IMAGE_IMPACT4','IMAGE_IMPACTMULTI','IMAGE_IMPACTREDBRICK2','IMAGE_IMPACTBRICK2','IMAGE_IMPACTBRICK3']:
targets.append(NAMES[n])
# smoke sprites
for n in ['IMAGE_SMOKE1','IMAGE_SMOKE2','IMAGE_SMOKEBALLS1']:
targets.append(NAMES[n])
seen = set()
for i in targets:
if i in seen or i >= len(entries): continue
seen.add(i)
print(dump2(i, entries[i][0]))
File diff suppressed because it is too large. Load diff
-989
View File
@@ -1,989 +0,0 @@
[INFO ] GoldenEye 007 PC port starting (ntsc-final, 0c700852 larkspur) -- https://github.com/jkdansereau/goldeneye-pc-port
[INFO ] config: loaded data\ge007.ini
[INFO ] all-unlocked: RAM unlock flags seeded (Game.AllUnlocked=1)
[INFO ] romdataInit: ge007.ntsc-final.z64 (12582912 bytes) mapped at 0x10000000 (cart base), + model sidecars, + bg/stan sidecars
[INFO ] pcmodels: 512 sidecars (1315680 bytes) at 0x10C00000
[INFO ] pccg: 73 sidecars (3604378 bytes) at 0x10D41360
[INFO ] romdataInit: D230 byte-swapped 1 RAW16 wavetable range(s) in place
[NOTE ] SDL: created GL3.0 context
[NOTE ] GL: using GLSL version 130
[INFO ] video: 2979x1705 window (native 640x480)
[INFO ] audioInit: opened SDL audio device at 22050 Hz
[INFO ] input: ready (mask=0x1, 1 controller(s), aimSpeed=16)
[INFO ] ROM mapped at 0x10000000 (12582912 bytes); starting game
[NOTE ] first block on mq=00000001402864e0 from 0000000140109a52 (rel 0000000000109a52)
[INFO ] pcmodels: table patched (512 model entries)
[INFO ] pccg: table patched (73 bg/stan entries)
[NOTE ] timer set: t=0000000065d5fdc0 start=100000us period=0us mq=0000000065d5fd90
[NOTE ] first block on mq=0000000065d5fd90 from 0000000140110065 (rel 0000000000110065)
[NOTE ] D51 vi post #1 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] timer fire: t=0000000065d5fdc0 mq=0000000065d5fd90
[NOTE ] timer set: t=0000000065d5fdc0 start=100000us period=0us mq=0000000065d5fd90
[NOTE ] timer fire: t=0000000065d5fdc0 mq=0000000065d5fd90
[NOTE ] first block on mq=0000000140288920 from 000000014010d759 (rel 000000000010d759)
[NOTE ] first block on mq=00000001402888a0 from 000000014010d787 (rel 000000000010d787)
[NOTE ] timer set: t=0000000065d5fdc0 start=100000us period=0us mq=0000000065d5fd90
[NOTE ] timer fire: t=0000000065d5fdc0 mq=0000000065d5fd90
[NOTE ] timer set: t=0000000065d5fdc0 start=100000us period=0us mq=0000000065d5fd90
[NOTE ] timer fire: t=0000000065d5fdc0 mq=0000000065d5fd90
[NOTE ] romdataFixupMusicSeqTable: partial decode, seqCount 63 > capacity 1 (full table follows)
[NOTE ] first block on mq=0000000140287cd0 from 000000014010a4c1 (rel 000000000010a4c1)
[NOTE ] first block on mq=0000000140287d38 from 000000014010a5b8 (rel 000000000010a5b8)
[NOTE ] first block on mq=0000000140285c20 from 00000001401105c2 (rel 00000000001105c2)
[NOTE ] frame 1 rendered in 44488 us
[NOTE ] frame 2 rendered in 44 us
[NOTE ] frame 3 rendered in 66 us
[NOTE ] frame 4 rendered in 27906 us
[INFO ] eeprom: loaded data\ge007.eep
[NOTE ] frame 5 rendered in 3963 us
[NOTE ] D51 vi post #61 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #121 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #181 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #241 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #301 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 300 rendered in 81 us
[NOTE ] D51 vi post #361 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #421 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #481 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #541 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #601 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 600 rendered in 77 us
[NOTE ] D51 vi post #661 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #721 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #781 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #841 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #901 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 900 rendered in 45 us
[NOTE ] D51 vi post #961 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1021 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1081 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1141 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1201 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 1200 rendered in 34 us
[NOTE ] D51 vi post #1261 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1321 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1381 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1441 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1501 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 1500 rendered in 200 us
[NOTE ] D51 vi post #1561 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1621 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1681 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1741 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1801 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 1800 rendered in 63 us
[NOTE ] D51 vi post #1861 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1921 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1981 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2041 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2101 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 2100 rendered in 1151 us
[NOTE ] D51 vi post #2161 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2221 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2281 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2341 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2401 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 2400 rendered in 75 us
[NOTE ] D51 vi post #2461 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=254 list=00000000701ccdf0 off=0 size=7 landcmd=0x02 global=0
[NOTE ] D51 vi post #2521 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2581 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2641 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2701 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 2700 rendered in 331 us
[NOTE ] D51 vi post #2761 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2821 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2881 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2941 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #3001 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 3000 rendered in 642 us
[NOTE ] D51 vi post #3061 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=4 list=000000014014d360 off=167 size=1 landcmd=0x95 global=1
[NOTE ] D51 vi post #3121 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=50 size=4 landcmd=0x9c global=0
D309: PRINT chr=88 list=00000000701cca30 off=112 size=4 landcmd=0x9a global=0
[NOTE ] D51 vi post #3181 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #3241 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #3301 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 3300 rendered in 361 us
[NOTE ] D51 vi post #3361 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #3421 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #3481 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #3541 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #3601 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 3600 rendered in 293 us
[NOTE ] D51 vi post #3661 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=50 size=4 landcmd=0x9c global=0
[NOTE ] D51 vi post #3721 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #3781 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #3841 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #3901 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 3900 rendered in 268 us
[NOTE ] D51 vi post #3961 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4021 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4081 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4141 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4201 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=50 size=4 landcmd=0x9c global=0
[NOTE ] frame 4200 rendered in 523 us
[NOTE ] D51 vi post #4261 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4321 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4381 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4441 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4501 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 4500 rendered in 312 us
[NOTE ] D51 vi post #4561 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4621 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4681 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4741 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4801 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 4800 rendered in 416 us
[NOTE ] D51 vi post #4861 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4921 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4981 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5041 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5101 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 5100 rendered in 250 us
[NOTE ] D51 vi post #5161 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5221 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5281 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5341 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5401 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 5400 rendered in 116 us
[NOTE ] D51 vi post #5461 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5521 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5581 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5641 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5701 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 5700 rendered in 530 us
[NOTE ] D51 vi post #5761 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5821 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5881 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5941 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6001 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 6000 rendered in 539 us
[NOTE ] D51 vi post #6061 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6121 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6181 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6241 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6301 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 6300 rendered in 283 us
[NOTE ] D51 vi post #6361 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6421 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6481 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6541 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6601 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 6600 rendered in 413 us
[NOTE ] D51 vi post #6661 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6721 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6781 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6841 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=50 size=4 landcmd=0x9c global=0
[NOTE ] D51 vi post #6901 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 6900 rendered in 580 us
[NOTE ] D51 vi post #6961 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7021 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7081 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7141 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7201 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 7200 rendered in 437 us
[NOTE ] D51 vi post #7261 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=50 size=4 landcmd=0x9c global=0
D309: PRINT chr=88 list=00000000701cca30 off=180 size=4 landcmd=0x9a global=0
[NOTE ] D51 vi post #7321 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7381 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7441 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7501 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 7500 rendered in 605 us
[NOTE ] D51 vi post #7561 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7621 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7681 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7741 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7801 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 7800 rendered in 294 us
[NOTE ] D51 vi post #7861 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=24 list=000000014014d360 off=4 size=1 landcmd=0x02 global=1
[NOTE ] D51 vi post #7921 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7981 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8041 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8101 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 8100 rendered in 303 us
[NOTE ] D51 vi post #8161 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=50 size=4 landcmd=0x9c global=0
D309: PRINT chr=88 list=00000000701cca30 off=200 size=4 landcmd=0x9a global=0
[NOTE ] D51 vi post #8221 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8281 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8341 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8401 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 8400 rendered in 451 us
[NOTE ] D51 vi post #8461 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8521 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8581 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8641 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8701 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=50 size=4 landcmd=0x9c global=0
D309: PRINT chr=88 list=00000000701cca30 off=220 size=4 landcmd=0x9a global=0
[NOTE ] frame 8700 rendered in 908 us
[NOTE ] D51 vi post #8761 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8821 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8881 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8941 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #9001 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=50 size=4 landcmd=0x9c global=0
D309: PRINT chr=88 list=00000000701cca30 off=288 size=4 landcmd=0x1c global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
[NOTE ] frame 9000 rendered in 385 us
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #9061 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #9121 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=302 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #9181 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #9241 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #9301 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] frame 9300 rendered in 947 us
[NOTE ] D51 vi post #9361 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #9421 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #9481 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #9541 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #9601 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] frame 9600 rendered in 794 us
[NOTE ] D51 vi post #9661 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #9721 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #9781 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #9841 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #9901 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] frame 9900 rendered in 400 us
[NOTE ] D51 vi post #9961 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #10021 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #10081 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #10141 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #10201 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] frame 10200 rendered in 210 us
[NOTE ] D51 vi post #10261 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #10321 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #10381 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=72 list=000000014014d360 off=167 size=1 landcmd=0x95 global=1
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #10441 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #10501 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] frame 10500 rendered in 136 us
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #10561 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #10621 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #10681 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #10741 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #10801 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] frame 10800 rendered in 354 us
[NOTE ] D51 vi post #10861 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #10921 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #10981 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #11041 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #11101 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] frame 11100 rendered in 229 us
[NOTE ] D51 vi post #11161 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #11221 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #11281 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #11341 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #11401 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] frame 11400 rendered in 186 us
[NOTE ] D51 vi post #11461 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #11521 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #11581 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #11641 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #11701 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] frame 11700 rendered in 164 us
[NOTE ] D51 vi post #11761 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #11821 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #11881 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #11941 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #12001 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #12061 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 12000 rendered in 240 us
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #12121 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #12181 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #12241 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #12301 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #12361 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 12300 rendered in 572 us
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #12421 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #12481 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #12541 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #12601 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #12661 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 12600 rendered in 494 us
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #12721 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #12781 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #12841 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #12901 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #12961 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 12900 rendered in 214 us
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #13021 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #13081 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #13141 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #13201 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #13261 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 13200 rendered in 125 us
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #13321 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: PRINT chr=88 list=00000000701cca30 off=322 size=4 landcmd=0x03 global=0
[NOTE ] D51 vi post #13381 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13441 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13501 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13561 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 13500 rendered in 179 us
[NOTE ] D51 vi post #13621 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13681 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13741 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13801 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13861 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 13800 rendered in 301 us
[NOTE ] D51 vi post #13921 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13981 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14041 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14101 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14161 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 14100 rendered in 345 us
[NOTE ] D51 vi post #14221 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14281 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14341 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14401 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14461 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 14400 rendered in 294 us
[NOTE ] D51 vi post #14521 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14581 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14641 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14701 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14761 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 14700 rendered in 1025 us
[NOTE ] D51 vi post #14821 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14881 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14941 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15001 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15061 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 15000 rendered in 222 us
[NOTE ] D51 vi post #15121 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15181 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15241 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15301 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15361 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 15300 rendered in 584 us
[NOTE ] D51 vi post #15421 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15481 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15541 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15601 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15661 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 15600 rendered in 499 us
[NOTE ] D51 vi post #15721 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15781 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15841 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15901 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15961 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 15900 rendered in 295 us
[NOTE ] D51 vi post #16021 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16081 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16141 mq=00000001402864e0 msg=666 valid=1/8 ret=0
D309: FAIL-gate chr=9 act=4 deadOrShot=1 seen=0 stage=39 curload=39 mainstage=-1 cammode=4 stoptime=0
[NOTE ] D51 vi post #16201 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16261 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 16200 rendered in 346 us
[NOTE ] D51 vi post #16321 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16381 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16441 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16501 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16561 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 16500 rendered in 225 us
[NOTE ] D51 vi post #16621 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16681 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16741 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16801 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16861 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 16800 rendered in 442 us
[NOTE ] D51 vi post #16921 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16981 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17041 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17101 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17161 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 17100 rendered in 118 us
[NOTE ] D51 vi post #17221 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17281 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17341 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17401 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17461 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 17400 rendered in 777 us
[NOTE ] D51 vi post #17521 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17581 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17641 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17701 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17761 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 17700 rendered in 833 us
[NOTE ] D51 vi post #17821 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17881 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17941 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18001 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18061 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 18000 rendered in 716 us
[NOTE ] D51 vi post #18121 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18181 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18241 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18301 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18361 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 18300 rendered in 419 us
[NOTE ] D51 vi post #18421 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18481 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18541 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18601 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18661 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 18600 rendered in 589 us
[NOTE ] D51 vi post #18721 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18781 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18841 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18901 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18961 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 18900 rendered in 583 us
[NOTE ] D51 vi post #19021 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19081 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19141 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19201 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19261 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 19200 rendered in 664 us
[NOTE ] D51 vi post #19321 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19381 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19441 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19501 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19561 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 19500 rendered in 200 us
[NOTE ] D51 vi post #19621 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19681 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19741 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19801 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19861 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 19800 rendered in 990 us
[NOTE ] D51 vi post #19921 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19981 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20041 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20101 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20161 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 20100 rendered in 519 us
[NOTE ] D51 vi post #20221 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20281 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20341 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20401 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20461 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 20400 rendered in 228 us
[NOTE ] D51 vi post #20521 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20581 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20641 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20701 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20761 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 20700 rendered in 863 us
[NOTE ] D51 vi post #20821 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20881 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20941 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21001 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21061 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 21000 rendered in 664 us
[NOTE ] D51 vi post #21121 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21181 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21241 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21301 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21361 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 21300 rendered in 568 us
[NOTE ] D51 vi post #21421 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21481 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21541 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21601 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21661 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 21600 rendered in 485 us
[NOTE ] D51 vi post #21721 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21781 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21841 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21901 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21961 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 21900 rendered in 484 us
[NOTE ] D51 vi post #22021 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22081 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22141 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22201 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22261 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 22200 rendered in 288 us
[NOTE ] D51 vi post #22321 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22381 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22441 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22501 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22561 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 22500 rendered in 174 us
[NOTE ] D51 vi post #22621 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22681 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22741 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22801 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22861 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 22800 rendered in 115 us
[NOTE ] D51 vi post #22921 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22981 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23041 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23101 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23161 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 23100 rendered in 702 us
[NOTE ] D51 vi post #23221 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23281 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23341 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23401 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23461 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 23400 rendered in 399 us
[NOTE ] D51 vi post #23521 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23581 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23641 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23701 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23761 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 23700 rendered in 924 us
[NOTE ] D51 vi post #23821 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23881 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23941 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #24001 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #24061 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 24000 rendered in 733 us
[NOTE ] D51 vi post #24121 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #24181 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #24241 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #24301 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #24361 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 24300 rendered in 354 us
[NOTE ] D51 vi post #24421 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #24481 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #24541 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #24601 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #24661 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 24600 rendered in 509 us
[NOTE ] D51 vi post #24721 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #24781 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #24841 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #24901 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #24961 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 24900 rendered in 663 us
[NOTE ] D51 vi post #25021 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #25081 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #25141 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #25201 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #25261 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 25200 rendered in 548 us
[NOTE ] D51 vi post #25321 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #25381 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #25441 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #25501 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #25561 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 25500 rendered in 590 us
[NOTE ] D51 vi post #25621 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #25681 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #25741 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #25801 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #25861 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 25800 rendered in 343 us
[NOTE ] D51 vi post #25921 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #25981 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #26041 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #26101 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #26161 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 26100 rendered in 251 us
[NOTE ] D51 vi post #26221 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #26281 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #26341 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #26401 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #26461 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 26400 rendered in 820 us
[NOTE ] D51 vi post #26521 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #26581 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #26641 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #26701 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #26761 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 26700 rendered in 440 us
[NOTE ] D51 vi post #26821 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #26881 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #26941 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #27001 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #27061 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 27000 rendered in 262 us
[NOTE ] D51 vi post #27121 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #27181 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #27241 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #27301 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #27361 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 27300 rendered in 379 us
[NOTE ] D51 vi post #27421 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[INFO ] video: window closed
[INFO ] config: wrote data\ge007.ini
File diff suppressed because it is too large. Load diff
-611
View File
@@ -1,611 +0,0 @@
[INFO ] GoldenEye 007 PC port starting (ntsc-final, 0c700852 larkspur) -- https://github.com/jkdansereau/goldeneye-pc-port
[INFO ] config: loaded data\ge007.ini
[INFO ] all-unlocked: RAM unlock flags seeded (Game.AllUnlocked=1)
[INFO ] romdataInit: ge007.ntsc-final.z64 (12582912 bytes) mapped at 0x10000000 (cart base), + model sidecars, + bg/stan sidecars
[INFO ] pcmodels: 512 sidecars (1315680 bytes) at 0x10C00000
[INFO ] pccg: 73 sidecars (3604378 bytes) at 0x10D41360
[INFO ] romdataInit: D230 byte-swapped 1 RAW16 wavetable range(s) in place
[NOTE ] SDL: created GL3.0 context
[NOTE ] GL: using GLSL version 130
[INFO ] video: 2979x1705 window (native 640x480)
[INFO ] audioInit: opened SDL audio device at 22050 Hz
[INFO ] input: ready (mask=0x1, 1 controller(s), aimSpeed=16)
[INFO ] ROM mapped at 0x10000000 (12582912 bytes); starting game
[NOTE ] first block on mq=00000001402864e0 from 0000000140109952 (rel 0000000000109952)
[INFO ] pcmodels: table patched (512 model entries)
[INFO ] pccg: table patched (73 bg/stan entries)
[NOTE ] timer set: t=000000006631fdc0 start=100000us period=0us mq=000000006631fd90
[NOTE ] first block on mq=000000006631fd90 from 000000014010ff65 (rel 000000000010ff65)
[NOTE ] D51 vi post #1 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] timer fire: t=000000006631fdc0 mq=000000006631fd90
[NOTE ] timer set: t=000000006631fdc0 start=100000us period=0us mq=000000006631fd90
[NOTE ] timer fire: t=000000006631fdc0 mq=000000006631fd90
[NOTE ] first block on mq=0000000140288920 from 000000014010d659 (rel 000000000010d659)
[NOTE ] first block on mq=00000001402888a0 from 000000014010d687 (rel 000000000010d687)
[NOTE ] timer set: t=000000006631fdc0 start=100000us period=0us mq=000000006631fd90
[NOTE ] timer fire: t=000000006631fdc0 mq=000000006631fd90
[NOTE ] timer set: t=000000006631fdc0 start=100000us period=0us mq=000000006631fd90
[NOTE ] timer fire: t=000000006631fdc0 mq=000000006631fd90
[NOTE ] romdataFixupMusicSeqTable: partial decode, seqCount 63 > capacity 1 (full table follows)
[NOTE ] first block on mq=0000000140287cd0 from 000000014010a3c1 (rel 000000000010a3c1)
[NOTE ] first block on mq=0000000140287d38 from 000000014010a4b8 (rel 000000000010a4b8)
[NOTE ] first block on mq=0000000140285c20 from 00000001401104c2 (rel 00000000001104c2)
[NOTE ] frame 1 rendered in 44332 us
[NOTE ] frame 2 rendered in 40 us
[NOTE ] frame 3 rendered in 484 us
[NOTE ] frame 4 rendered in 27576 us
[INFO ] eeprom: loaded data\ge007.eep
[NOTE ] frame 5 rendered in 11471 us
[NOTE ] D51 vi post #61 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #121 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #181 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #241 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #301 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 300 rendered in 81 us
[NOTE ] D51 vi post #361 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #421 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #481 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #541 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #601 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 600 rendered in 217 us
[NOTE ] D51 vi post #661 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #721 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #781 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #841 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #901 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 900 rendered in 45 us
[NOTE ] D51 vi post #961 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1021 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1081 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1141 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1201 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 1200 rendered in 59 us
[NOTE ] D51 vi post #1261 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1321 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1381 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1441 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1501 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 1500 rendered in 203 us
[NOTE ] D51 vi post #1561 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1621 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1681 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1741 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1801 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 1800 rendered in 62 us
[NOTE ] D51 vi post #1861 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1921 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #1981 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2041 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2101 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 2100 rendered in 173 us
[NOTE ] D51 vi post #2161 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2221 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2281 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2341 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2401 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 2400 rendered in 96 us
[NOTE ] D51 vi post #2461 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2521 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2581 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2641 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2701 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 2700 rendered in 93 us
[NOTE ] D51 vi post #2761 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2821 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2881 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #2941 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #3001 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 3000 rendered in 91 us
[NOTE ] D51 vi post #3061 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #3121 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #3181 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #3241 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #3301 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 3300 rendered in 78 us
[NOTE ] D51 vi post #3361 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #3421 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #3481 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #3541 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #3601 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 3600 rendered in 82 us
[NOTE ] D51 vi post #3661 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #3721 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #3781 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #3841 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #3901 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 3900 rendered in 86 us
[NOTE ] D51 vi post #3961 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4021 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4081 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4141 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4201 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 4200 rendered in 2123 us
[NOTE ] D51 vi post #4261 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4321 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4381 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4441 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4501 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 4500 rendered in 143 us
[NOTE ] D51 vi post #4561 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4621 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4681 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4741 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4801 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 4800 rendered in 78 us
[NOTE ] D51 vi post #4861 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4921 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #4981 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5041 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5101 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 5100 rendered in 84 us
[NOTE ] D51 vi post #5161 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5221 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5281 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5341 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5401 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5461 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 5400 rendered in 33 us
[NOTE ] D51 vi post #5521 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5581 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5641 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5701 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5761 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 5700 rendered in 211 us
[NOTE ] D51 vi post #5821 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5881 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #5941 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6001 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6061 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 6000 rendered in 31 us
[NOTE ] D51 vi post #6121 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6181 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6241 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6301 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6361 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 6300 rendered in 103 us
[NOTE ] D51 vi post #6421 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6481 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6541 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6601 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6661 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 6600 rendered in 89 us
[NOTE ] D51 vi post #6721 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6781 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6841 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6901 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #6961 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 6900 rendered in 96 us
[NOTE ] D51 vi post #7021 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7081 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7141 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7201 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7261 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 7200 rendered in 98 us
[NOTE ] D51 vi post #7321 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7381 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7441 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7501 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7561 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 7500 rendered in 82 us
[NOTE ] D51 vi post #7621 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7681 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7741 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7801 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7861 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 7800 rendered in 153 us
[NOTE ] D51 vi post #7921 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #7981 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8041 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8101 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8161 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 8100 rendered in 96 us
[NOTE ] D51 vi post #8221 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8281 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8341 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8401 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8461 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] frame 8400 rendered in 108 us
[D156] bad anim frame guarded: frame=-1.6708e+31 animframe1=-1.6708e+31 speed=0.220735 playspeed=1 newspeed=-3.23355e+07 oldspeed=-1.75136e+18 timespeed=0 elapsespeed=-3.72072e-26 unkb0=0 unk88=12 anim=00000000706af530
[NOTE ] D51 vi post #8521 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8581 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8641 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8701 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8761 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8821 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8881 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #8941 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[ERROR] kernel heartbeat: no frame rendered for 8014 ms (frames=8424); state:
[ERROR] T0(id=3) os=0000000140285e20 entry_rel=0000000000108b00 started=1 exited=0
[ERROR] T1(id=1) os=0000000140285fe0 entry_rel=00000000001087e0 started=1 exited=1
[ERROR] T2(id=0) os=00000001402861a0 entry_rel=00000000000e0be0 started=1 exited=1
[ERROR] T3(id=2) os=0000000140285c60 entry_rel=0000000000109920 started=1 exited=0
[ERROR] T4(id=4) os=0000000140287b10 entry_rel=000000000010a360 started=1 exited=0
[ERROR] mq=0000000140285c20 valid=32/32 first=22
[ERROR] mq=00000001402864e0 valid=0/8 first=2
[ERROR] mq=0000000140286548 valid=1/8 first=2
[ERROR] mq=00000001402983c0 valid=0/1 first=0
[ERROR] mq=0000000140288960 valid=0/1 first=0
[ERROR] mq=0000000140288920 valid=0/1 first=0
[ERROR] mq=00000001402888e0 valid=0/1 first=0
[ERROR] mq=00000001402888a0 valid=0/1 first=0
[ERROR] mq=00000001402889a0 valid=1/10 first=1
[ERROR] mq=000000006631fd90 valid=0/0 first=0
[ERROR] mq=00000001401f8700 valid=0/8 first=0
[ERROR] mq=0000000140287d38 valid=0/8 first=2
[ERROR] mq=0000000140287cd0 valid=0/8 first=3
[ERROR] mq=0000000140286840 valid=1/64 first=10
[ERROR] viRetraceMQ=00000001402864e0 msg=666 tickInterval=16666 us
[ERROR] [thread 32268 'mainThread']
[ERROR] #0 0000000140130942 ?
[ERROR] #1 000000014008497e ?
[ERROR] #2 0000000140085497 ?
[ERROR] #3 000000014000aaf0 ?
[ERROR] #4 0000000140014b24 ?
[ERROR] #5 000000014001be69 ?
[ERROR] #6 000000014001f60e ?
[ERROR] #7 000000014007cca1 ?
[ERROR] [thread 10432 'shedThread']
[ERROR] #0 00007ffb4fb4e104 NtWaitForMultipleObjects+14
[ERROR] #1 00007ffb4d580d10 WaitForMultipleObjectsEx+f0
[ERROR] #2 00007ffb4d580c0e WaitForMultipleObjects+e
[ERROR] #3 00007ffb4776242a pthread_cond_init+18a
[ERROR] #4 00007ffb477626ed pthread_cond_init+44d
[ERROR] #5 00007ffb47762ec7 pthread_cond_wait+217
[ERROR] #6 00000001400de2db ?
[ERROR] #7 0000000140109952 ?
[ERROR] [thread 39316 'audioThread']
[ERROR] #0 00007ffb4fb4e104 NtWaitForMultipleObjects+14
[ERROR] #1 00007ffb4d580d10 WaitForMultipleObjectsEx+f0
[ERROR] #2 00007ffb4d580c0e WaitForMultipleObjects+e
[ERROR] #3 00007ffb4776242a pthread_cond_init+18a
[ERROR] #4 00007ffb477626ed pthread_cond_init+44d
[ERROR] #5 00007ffb47762ec7 pthread_cond_wait+217
[ERROR] #6 00000001400de2db ?
[ERROR] #7 000000014010a4b8 ?
[NOTE ] D51 vi post #9001 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #9061 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #9121 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #9181 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #9241 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[ERROR] kernel heartbeat: no frame rendered for 13020 ms (frames=8424); state:
[ERROR] T0(id=3) os=0000000140285e20 entry_rel=0000000000108b00 started=1 exited=0
[ERROR] T1(id=1) os=0000000140285fe0 entry_rel=00000000001087e0 started=1 exited=1
[ERROR] T2(id=0) os=00000001402861a0 entry_rel=00000000000e0be0 started=1 exited=1
[ERROR] T3(id=2) os=0000000140285c60 entry_rel=0000000000109920 started=1 exited=0
[ERROR] T4(id=4) os=0000000140287b10 entry_rel=000000000010a360 started=1 exited=0
[ERROR] mq=0000000140285c20 valid=32/32 first=22
[ERROR] mq=00000001402864e0 valid=0/8 first=6
[ERROR] mq=0000000140286548 valid=1/8 first=6
[ERROR] mq=00000001402983c0 valid=0/1 first=0
[ERROR] mq=0000000140288960 valid=0/1 first=0
[ERROR] mq=0000000140288920 valid=0/1 first=0
[ERROR] mq=00000001402888e0 valid=0/1 first=0
[ERROR] mq=00000001402888a0 valid=0/1 first=0
[ERROR] mq=00000001402889a0 valid=1/10 first=9
[ERROR] mq=000000006631fd90 valid=0/0 first=0
[ERROR] mq=00000001401f8700 valid=0/8 first=0
[ERROR] mq=0000000140287d38 valid=0/8 first=6
[ERROR] mq=0000000140287cd0 valid=0/8 first=7
[ERROR] mq=0000000140286840 valid=3/64 first=29
[ERROR] viRetraceMQ=00000001402864e0 msg=666 tickInterval=16666 us
[ERROR] [thread 32268 'mainThread']
[ERROR] #0 00000001400812b0 ?
[ERROR] #1 00000001400848ff ?
[ERROR] #2 0000000140085497 ?
[ERROR] #3 000000014000aaf0 ?
[ERROR] #4 0000000140014b24 ?
[ERROR] #5 000000014001be69 ?
[ERROR] #6 000000014001f60e ?
[ERROR] #7 000000014007cca1 ?
[ERROR] [thread 10432 'shedThread']
[ERROR] #0 00007ffb4fb4e104 NtWaitForMultipleObjects+14
[ERROR] #1 00007ffb4d580d10 WaitForMultipleObjectsEx+f0
[ERROR] #2 00007ffb4d580c0e WaitForMultipleObjects+e
[ERROR] #3 00007ffb4776242a pthread_cond_init+18a
[ERROR] #4 00007ffb477626ed pthread_cond_init+44d
[ERROR] #5 00007ffb47762ec7 pthread_cond_wait+217
[ERROR] #6 00000001400de2db ?
[ERROR] #7 0000000140109952 ?
[ERROR] [thread 39316 'audioThread']
[ERROR] #0 00007ffb4fb4e104 NtWaitForMultipleObjects+14
[ERROR] #1 00007ffb4d580d10 WaitForMultipleObjectsEx+f0
[ERROR] #2 00007ffb4d580c0e WaitForMultipleObjects+e
[ERROR] #3 00007ffb4776242a pthread_cond_init+18a
[ERROR] #4 00007ffb477626ed pthread_cond_init+44d
[ERROR] #5 00007ffb47762ec7 pthread_cond_wait+217
[ERROR] #6 00000001400de2db ?
[ERROR] #7 000000014010a4b8 ?
[NOTE ] D51 vi post #9301 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #9361 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #9421 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #9481 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #9541 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[ERROR] kernel heartbeat: no frame rendered for 18025 ms (frames=8424); state:
[ERROR] T0(id=3) os=0000000140285e20 entry_rel=0000000000108b00 started=1 exited=0
[ERROR] T1(id=1) os=0000000140285fe0 entry_rel=00000000001087e0 started=1 exited=1
[ERROR] T2(id=0) os=00000001402861a0 entry_rel=00000000000e0be0 started=1 exited=1
[ERROR] T3(id=2) os=0000000140285c60 entry_rel=0000000000109920 started=1 exited=0
[ERROR] T4(id=4) os=0000000140287b10 entry_rel=000000000010a360 started=1 exited=0
[ERROR] mq=0000000140285c20 valid=32/32 first=22
[ERROR] mq=00000001402864e0 valid=0/8 first=2
[ERROR] mq=0000000140286548 valid=1/8 first=2
[ERROR] mq=00000001402983c0 valid=0/1 first=0
[ERROR] mq=0000000140288960 valid=0/1 first=0
[ERROR] mq=0000000140288920 valid=0/1 first=0
[ERROR] mq=00000001402888e0 valid=0/1 first=0
[ERROR] mq=00000001402888a0 valid=0/1 first=0
[ERROR] mq=00000001402889a0 valid=1/10 first=8
[ERROR] mq=000000006631fd90 valid=0/0 first=0
[ERROR] mq=00000001401f8700 valid=0/8 first=0
[ERROR] mq=0000000140287d38 valid=0/8 first=2
[ERROR] mq=0000000140287cd0 valid=0/8 first=3
[ERROR] mq=0000000140286840 valid=2/64 first=4
[ERROR] viRetraceMQ=00000001402864e0 msg=666 tickInterval=16666 us
[ERROR] [thread 32268 'mainThread']
[ERROR] #0 0000000140081029 ?
[ERROR] #1 00000001400811f3 ?
[ERROR] #2 0000000140081288 ?
[ERROR] #3 00000001400848ff ?
[ERROR] #4 0000000140085497 ?
[ERROR] #5 000000014000aaf0 ?
[ERROR] #6 0000000140014b24 ?
[ERROR] #7 000000014001be69 ?
[ERROR] [thread 10432 'shedThread']
[ERROR] #0 00007ffb4fb4e104 NtWaitForMultipleObjects+14
[ERROR] #1 00007ffb4d580d10 WaitForMultipleObjectsEx+f0
[ERROR] #2 00007ffb4d580c0e WaitForMultipleObjects+e
[ERROR] #3 00007ffb4776242a pthread_cond_init+18a
[ERROR] #4 00007ffb477626ed pthread_cond_init+44d
[ERROR] #5 00007ffb47762ec7 pthread_cond_wait+217
[ERROR] #6 00000001400de2db ?
[ERROR] #7 0000000140109952 ?
[ERROR] [thread 39316 'audioThread']
[ERROR] #0 00007ffb4fb4e104 NtWaitForMultipleObjects+14
[ERROR] #1 00007ffb4d580d10 WaitForMultipleObjectsEx+f0
[ERROR] #2 00007ffb4d580c0e WaitForMultipleObjects+e
[ERROR] #3 00007ffb4776242a pthread_cond_init+18a
[ERROR] #4 00007ffb477626ed pthread_cond_init+44d
[ERROR] #5 00007ffb47762ec7 pthread_cond_wait+217
[ERROR] #6 00000001400de2db ?
[ERROR] #7 000000014010a4b8 ?
[NOTE ] D51 vi post #9601 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #9661 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #9721 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #9781 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #9841 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #9901 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #9961 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #10021 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #10081 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #10141 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #10201 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #10261 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #10321 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #10381 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #10441 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #10501 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #10561 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #10621 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #10681 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #10741 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #10801 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #10861 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #10921 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #10981 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #11041 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #11101 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #11161 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #11221 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #11281 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #11341 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #11401 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #11461 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #11521 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #11581 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #11641 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #11701 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #11761 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #11821 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #11881 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #11941 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #12001 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #12061 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #12121 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #12181 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #12241 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #12301 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #12361 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #12421 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #12481 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #12541 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #12601 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #12661 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #12721 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #12781 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #12841 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #12901 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #12961 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13021 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13081 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13141 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13201 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13261 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13321 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13381 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13441 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13501 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13561 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13621 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13681 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13741 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13801 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13861 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13921 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #13981 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14041 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14101 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14161 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14221 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14281 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14341 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14401 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14461 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14521 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14581 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14641 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14701 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14761 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14821 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14881 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #14941 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15001 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15061 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15121 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15181 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15241 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15301 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15361 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15421 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15481 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15541 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15601 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15661 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15721 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15781 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15841 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15901 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #15961 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16021 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16081 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16141 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16201 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16261 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16321 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16381 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16441 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16501 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16561 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16621 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16681 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16741 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16801 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16861 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16921 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #16981 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17041 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17101 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17161 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17221 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17281 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17341 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17401 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17461 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17521 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17581 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17641 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17701 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17761 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17821 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17881 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #17941 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18001 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18061 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18121 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18181 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18241 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18301 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18361 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18421 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18481 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18541 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18601 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18661 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18721 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18781 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18841 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18901 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #18961 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19021 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19081 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19141 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19201 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19261 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19321 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19381 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19441 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19501 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19561 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19621 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19681 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19741 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19801 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19861 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19921 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #19981 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20041 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D204: audio queue full (2928/2880 frames), dropped block #1
[NOTE ] D51 vi post #20101 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20161 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20221 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20281 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20341 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20401 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20461 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20521 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20581 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20641 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20701 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20761 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20821 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20881 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #20941 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21001 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21061 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21121 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21181 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21241 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21301 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21361 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21421 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21481 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21541 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21601 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21661 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21721 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21781 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21841 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21901 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #21961 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22021 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22081 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22141 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22201 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22261 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22321 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22381 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22441 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22501 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22561 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22621 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22681 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22741 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22801 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22861 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22921 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #22981 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23041 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23101 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23161 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23221 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23281 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23341 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23401 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23461 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23521 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23581 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23641 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23701 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23761 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23821 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23881 mq=00000001402864e0 msg=666 valid=1/8 ret=0
[NOTE ] D51 vi post #23941 mq=00000001402864e0 msg=666 valid=1/8 ret=0
-135
View File
@@ -1,135 +0,0 @@
# D318 Session Handoff — PRNG investigation (Facility / level_34, Ourumov-Trevelyan sequence)
**Status: mid-investigation. No verdict change yet. All work uncommitted.**
Previous context: `docs/HANDOFF.md`, README "Status", findings D318 in `docs/dev/findings.md`
(look up via `docs/dev/findings-index.csv`). This file supersedes the old "next steps" list.
## 1. The problem (user-reported symptoms)
N64 ground truth (GEPD bundle emulator, user has it at
`C:\Users\james\Games\Emulators\Nintendo 64\1964_GEPD_Edition\1964`): in the Facility
tank-room sequence, guards line up and HOLD FIRE during Ourumov's (c78) monologue/countdown
while Trevelyan (c67) kneels; no shooting until tanks detonate; ~1s later Ourumov executes
Trevelyan; then guards open fire on Bond.
Port symptoms:
- **Intermittent**: sometimes guards start shooting immediately (before/instead of the hold).
- **Ourumov "bends down a bit too far"** vs N64 even in "normal" runs — animation suspect:
possible misroute into the kneel-attack path `sub_GAME_7F0256F0` (selected by
`act_attack.unk54`: 1=standing `sub_GAME_7F025560`, 0=kneeling). The standing path is what
ai_22's AI_TRYFireOrAimAtTarget uses, so `unk54==0` during the countdown would be a bug.
- Sequence triggers spottily vs original; user suspects a **foundational** issue (PRNG stream
parity / tick pacing / objective register state) affecting other areas too.
## 2. What this session established (findings F1–F5)
- **F1 — Boot seed is wall-clock BY DESIGN, faithful to N64.** `src/boss.c:404`:
`randomSetSeed(osGetCount())`. N64 RSP timer varies per power-on; PC shim (`port/src/libultra.c`
`osGetCount`) feeds wall-clock scaled to 46.5 MHz. Per-run PRNG variation is original behavior,
NOT a port bug. D284 (M-140) transform fix stands.
- **F2 — Guard AI consumes the global PRNG heavily per tick.** Measured (15s headless
`-level_34`, `GE_D318R=1`): top callers `chrCheckTargetInSight` (~7.7 draws/tick),
`chrlvTickStand`, `ai`, `shuffle_player_ids` (3 draws EVERY main-loop iteration, even solo —
`src/boss.c:597`). Guard behavior is strongly seed-dependent by design ⇒ N64 holding fire
reliably under random per-boot seeds implies the **hold-fire gate is deterministic
(objective-register-driven), not RNG-driven**. This reframes the "guards fire immediately"
symptom toward objective-register/gate state rather than raw PRNG parity.
- **F3 — Coarse sim state was run-to-run identical** in no-input runs (chr hash `h` matched at
all samples) — weak check in an idle scene, not a determinism proof.
- **F4 — Residual run-to-run divergence remains even with pinned seed + GE_DETERM=1.** Draw
caller sequence diverges by draw ~346 (t≈15); 3548/4000 tick stamps differ. Suspect:
**tick pacing, not the PRNG** — `waitForNextFrame()` (`src/game/frametiming.c`) derives
`deltaFrames` from wall-clock elapsed time; `g_GlobalTimer += g_ClockTimer` (lv.c:1051) thus
advances a jittery 0/1/2 per rendered frame. Under GE_DETERM the virtual clock advances on the
scheduler thread and drifts against the main loop. N64 was single-threaded + VI-locked ⇒
exactly one tick/frame. **This is the foundational issue: it exists in every level.**
NOTE: not yet a clean verdict — GE_DETERM itself has pacing non-determinism (harness flaw).
- **F5 — MinGW `strtoull` mangles hex values > LLONG_MAX** (returns sign-extended low 32 bits;
`"deadbeefcafe0123"` → `ffffffffcafe0123`). Worked around with manual hex parsers in both new
files. Remember for any future 64-bit hex env parsing.
Also: N64 `g_randomSeed` RAM address = **0x80024460** (u64, big-endian; found by
instruction-pattern search). Initial constant 0xAB8D9F7781280783, but boss.c reseeds at boot.
## 3. Instrumentation added this session (all test-only, env-gated, port-layer)
| Env var | Behavior | File |
|---|---|---|
| `GE_D318T=1` | Timeline probe: obj-bit transitions, c78 phase/action/attack/entity changes, NEAR_MISS, c67 damage/death, **c78 anim internals on change** (`type_of_motion`, `unk54`, `endframe`, `frame1` — answers "bending down": `unk54==0` ⇒ kneel-route misfire), DET fingerprint line every 60 ticks (FNV-1a over all active chrs + full u64 seed + obj bits) | `port/src/d318watchdog.c` `d318TimelineTick()` (hooked in `src/game/lv.c` after `g_GlobalTimer += g_ClockTimer`) |
| `GE_D318R=1` | Per-draw PRNG logger: first 4000 `randomGetNext()` calls as `D318R: n=<i> t=<tick> ra=<retaddr>`; also logs every `randomSetSeed` (`SETSEED arg=... -> ...`) and GE_RSEED overrides | `port/src/random.c` `randomDrawLog()` |
| `GE_RSEED=<hex64>` | Pins the boot seed (overrides wall-clock) for determinism tests | `port/src/random.c` `randomSetSeed()` |
| `GE_RSEED_LV=<hex64>[@tick]` | Injects a seed at a chosen tick (default 0) — A/B parity vs N64 RAM read; DET lines then verify stream parity | `port/src/d318watchdog.c` top of `d318TimelineTick()` |
Resolving `ra=` addresses: `nm build-pc/ge007.x86_64.exe` (has symbols, no line info) → nearest
symbol below. Helper scripts in scratch: `d318r_cmp.py` (per-caller counts),
`d318r_seqcmp2.py` / `d318r_seqcmp3.py` (sequence divergence; seqcmp3 compares caller-only vs
tick stamps). Symbol dump: `scratch/syms.txt` (regenerate: `nm build-pc/ge007.x86_64.exe | awk '$2 ~ /[tTwW]/ {print $1, $3}'`).
Build is clean (`cmake --build build-pc`). Probe is silent without env vars (smoke-tested).
## 4. Experiments run (logs in scratch/)
- `d318t_det1/2.log`: two no-input runs, GE_D318T=1 → identical chr hash, divergent seeds
(explained by F1: different wall-clock boot seeds).
- `d318r_draws*.log` + `detC..F.log`: draw-caller analysis; `detE/F` = GE_DETERM=1 +
GE_RSEED=0123456789abcdef → caller sequence diverges by draw 346 (F4).
## 5. Next steps (prioritized)
1. **E2 — USER playtest (needs user):** one BAD + one GOOD tank-room run with `GE_D318T=1`,
capturing console: `ge007.x86_64.exe > scratch/d318t_playtest.log 2>&1` (MSYS2 MINGW64 shell,
build via `./build-pc.sh ntsc-final`). The obj-bit timeline discriminates "gate opened early"
(bit 0x04 set before it should) from "guards bypassing gate"; c78 anim-internals lines answer
the bending-down question (`unk54`/`type_of_motion`/`endframe`).
2. **E3 — USER reads N64 seed (needs user):** in 1964 debugger, read u64 at RAM **0x80024460**
when Facility gameplay starts; report value. Then run port with `GE_RSEED_LV=<value>` and
compare guard behavior + verify stream parity: DET lines log the running seed every 60 ticks;
a second emulator read a few seconds later should match the port's DET seed if streams are
in lockstep from the injection point. (Caveat: `-level_34` skips menu draws — inject at
gameplay start, not boot.)
3. **E1b — ME:** fix GE_DETERM main-loop/tick lock (or build single-threaded fixed-tick headless
harness) for a clean determinism verdict on F4. Lower priority until E2/E3 data lands.
4. If PRNG pacing (F4) confirmed as the behavioral culprit: it's a `port/`-layer fix candidate
(frametiming/pacing), NOT a game-code edit — but diagnose fully first; document in findings.md.
## 6. Open questions / holds
- **D318 verdict is in question.** The committed-in-working-tree framing ("as-authored latent
race, N64 has identical softlock") may be wrong: N64 reliably executes ~1s after detonation.
The derail path (section 0x2a → off=307) IS the normal execution flow on N64. If N64 never
freezes, the freeze branch is likely PC-specific — re-open D318 findings if E2/E3 confirm.
- **HOLD the D318 commit** (working tree only, uncommitted): if the verdict flips, the watchdog
(`port/src/d318watchdog.c` `d318WatchdogTick`, opt-out `GE_D318W=0`) should go opt-in or be
replaced by the real fix before the README auto-recovery claim ships.
- Regression-window suspect for guard behavior: D312/D313 commit (bullet-wall collision,
last gameplay-affecting change before mostly-working Sep 18 playtest3).
## 7. Git status (uncommitted)
Modified: `.github/release-notes.md`, `.gitignore`, `README.md`, `docs/dev/agentic-development.md`,
`docs/dev/findings-index.csv`, `docs/dev/findings.md`, `docs/index.md`,
`docs/media/goldeneye-gh-preview.gif`, `src/game/lv.c` (D318 hooks), **`port/src/random.c`**
(PRNG logging + GE_RSEED, this session).
Untracked: **`port/src/d318watchdog.c`** (watchdog + timeline probe + seed injection),
various `scratch/*` logs/scripts.
## 8. Key code map (verified this session)
- `src/boss.c:404-405` — boot PRNG reseed from osGetCount; `:596-597` — per-main-iteration
`lvlManageMpGame()` + `shuffle_player_ids()`.
- `src/game/lv.c:1023+` `lvlManageMpGame()` — g_ClockTimer (pause→0, else speedgraphframes),
`g_GlobalTimer += g_ClockTimer` at :1051, D318 hooks right after.
- `src/game/frametiming.c` — `waitForNextFrame()` wall-clock deltaFrames + D155 clamp
(max 6) + D193 telemetry (`GE_D193=1`).
- `src/game/model.c:4800+` `sub_GAME_7F072C10` — render-path function doing 3 PRNG draws per
vertex (dorottex/rotating-texture effect); also model.c:5251/5310. Render-path PRNG
consumption is a secondary parity concern (per presented frame, not per tick).
- `src/game/player.c:637` `shuffle_player_ids()` — 3 draws/call.
- `port/src/libultra.c:90+` — osGetCount wall-clock shim + GE_DETERM virtual clock (D117/M-52;
known pre-task-window non-determinism).
- `port/src/random.c` — PRNG transform (D284-verified) + this session's logging/overrides.
- ai_22 offsets (from prior sessions): off=38 pre-aim, 44 wait loop, 69+ monologue cascade,
272 execution label, 295 sets bit 0x04, 302 combat section 0x2a, 307 update, 321 sleep/stop.
- CHRFLAG_NEAR_MISS = 0x4 (bondconstants.h), set chr.c:3806 (Bond bullet bounds), cleared
per-tick (one-frame window).
- N64 emulator: `C:\Users\james\Games\Emulators\Nintendo 64\1964_GEPD_Edition\1964` (user-provided).
-23
View File
@@ -1,23 +0,0 @@
import re, sys
src = open('assets/obseg/setup/UsetuparkZ.c', encoding='utf-8', errors='replace').read()
hdr = open('src/bondaicommands.h', encoding='utf-8', errors='replace').read()
lens = dict(re.findall(r'#define (\w+)_LENGTH (0x[0-9a-f]+)', hdr))
def dis(name):
m = re.search(r'u8 %s\[\] = \{(.*?)\n\};' % name, src, re.S)
body = m.group(1)
off = 0; out=[]
for line in body.splitlines():
line=line.strip().rstrip(',')
if not line: continue
nm = line.split('(')[0].split()[0]
L = lens.get(nm)
if L is None:
out.append(f"{off:5d} ?? {line[:60]}"); continue
L=int(L,16)
out.append(f"{off:5d} +{L:<2d} {line[:70]}")
off+=L
return out, off
for name in sys.argv[1:]:
lines,total = dis(name)
print(f"== {name} (total {total} bytes) ==")
for l in lines: print(l)
-28
View File
@@ -1,28 +0,0 @@
1785 ra=000000014002bcc5
761 ra=00000001400359a5
690 ra=000000014009be4a
557 ra=000000014003c870
64 ra=000000014002c9b1
63 ra=0000000140028c85
14 ra=0000000140028d7a
9 ra=0000000140030848
6 ra=000000014006091a
6 ra=00000001400608e8
6 ra=00000001400608b5
6 ra=0000000140060881
6 ra=0000000140060843
6 ra=00000001400607fe
6 ra=00000001400607b2
2 ra=000000014000a4c9
2 ra=000000014000a474
1 ra=000000014009bb15
1 ra=0000000140077391
1 ra=0000000140077378
1 ra=000000014007735f
1 ra=000000014003041d
1 ra=000000014002b145
1 ra=00000001400220b1
1 ra=000000014000a5d8
1 ra=000000014000a5a5
1 ra=000000014000a54f
1 ra=000000014000a51c
-28
View File
@@ -1,28 +0,0 @@
1785 ra=000000014002bcc5
761 ra=00000001400359a5
690 ra=000000014009be4a
557 ra=000000014003c870
64 ra=000000014002c9b1
63 ra=0000000140028c85
14 ra=0000000140028d7a
9 ra=0000000140030848
6 ra=000000014006091a
6 ra=00000001400608e8
6 ra=00000001400608b5
6 ra=0000000140060881
6 ra=0000000140060843
6 ra=00000001400607fe
6 ra=00000001400607b2
2 ra=000000014000a4c9
2 ra=000000014000a474
1 ra=000000014009bb15
1 ra=0000000140077391
1 ra=0000000140077378
1 ra=000000014007735f
1 ra=000000014003041d
1 ra=000000014002b145
1 ra=00000001400220b1
1 ra=000000014000a5d8
1 ra=000000014000a5a5
1 ra=000000014000a54f
1 ra=000000014000a51c
-29
View File
@@ -1,29 +0,0 @@
1789 ra=000000014002bcc5
753 ra=00000001400359a5
693 ra=000000014009be4a
547 ra=000000014003c870
64 ra=000000014002c9b1
63 ra=0000000140028c85
14 ra=0000000140028d7a
11 ra=00000001400346c4
9 ra=0000000140030848
6 ra=000000014006091a
6 ra=00000001400608e8
6 ra=00000001400608b5
6 ra=0000000140060881
6 ra=0000000140060843
6 ra=00000001400607fe
6 ra=00000001400607b2
2 ra=000000014000a4c9
2 ra=000000014000a474
1 ra=000000014009bb15
1 ra=0000000140077391
1 ra=0000000140077378
1 ra=000000014007735f
1 ra=000000014003041d
1 ra=000000014002b145
1 ra=00000001400220b1
1 ra=000000014000a5d8
1 ra=000000014000a5a5
1 ra=000000014000a54f
1 ra=000000014000a51c
-37
View File
@@ -1,37 +0,0 @@
import bisect, sys
syms = []
for line in open("scratch/syms.txt"):
p = line.split()
if len(p) >= 2:
try:
syms.append((int(p[0], 16), p[1]))
except ValueError:
pass
syms.sort()
keys = [s[0] for s in syms]
def resolve(ra):
a = int(ra, 16)
i = bisect.bisect_right(keys, a) - 1
if i < 0:
return "??"
b, n = syms[i]
return "%s+%x" % (n, a - b)
def counts(p):
d = {}
for line in open(p):
q = line.split()
if len(q) >= 2:
d[resolve(q[1].replace("ra=", ""))] = int(q[0])
return d
a = counts("scratch/d318r_addrs1.txt")
b = counts("scratch/d318r_addrs2.txt")
allk = sorted(set(a) | set(b), key=lambda k: -(a.get(k, 0) + b.get(k, 0)))
print("%-45s %5s %5s" % ("caller", "run1", "run2"))
for k in allk[:18]:
mark = " <== DIFFERS" if a.get(k, 0) != b.get(k, 0) else ""
print("%-45s %5d %5d%s" % (k, a.get(k, 0), b.get(k, 0), mark))
print("total draws:", sum(a.values()), sum(b.values()))
-30
View File
@@ -1,30 +0,0 @@
import re, sys
def seq(p):
out = []
for line in open(p, encoding="utf8", errors="replace"):
m = re.search(r"n=(\d+) t=(\d+) ra=([0-9a-f]+)", line)
if m:
out.append((int(m.group(1)), int(m.group(2)), m.group(3)))
return out
a = seq("scratch/detA.log")
b = seq("scratch/detB.log")
print("draws A:", len(a), " B:", len(b))
# find first divergence in (t, ra) sequence
n = min(len(a), len(b))
first = None
for i in range(n):
if a[i][1:] != b[i][1:]:
first = i
break
if first is None:
print("sequences identical over", n, "draws; length diff only")
else:
print("first divergence at draw index", first)
for j in range(max(0, first - 3), min(n, first + 4)):
mark = " <==" if j == first else ""
sa = a[j]; sb = b[j]
same = "same" if sa[1:] == sb[1:] else "DIFF"
print(f" [{j}] A: t={sa[1]:4d} ra={sa[2]} B: t={sb[1]:4d} ra={sb[2]} {same}{mark}")
-27
View File
@@ -1,27 +0,0 @@
import re, sys
def seq(p):
out = []
for line in open(p, encoding="utf8", errors="replace"):
m = re.search(r"n=(\d+) t=(\d+) ra=([0-9a-f]+)", line)
if m:
out.append((int(m.group(2)), m.group(3)))
return out
a = seq(sys.argv[1])
b = seq(sys.argv[2])
print("draws:", len(a), len(b))
n = min(len(a), len(b))
first = None
for i in range(n):
if a[i] != b[i]:
first = i
break
if first is None:
print("FULL SEQUENCE IDENTICAL over", n, "draws (tick, caller)")
else:
print("first divergence at draw index", first)
for j in range(max(0, first - 2), min(n, first + 3)):
tag = "same" if a[j] == b[j] else "DIFF <=="
print(" [%d] A t=%4d ra=%s B t=%4d ra=%s %s"
% (j, a[j][0], a[j][1], b[j][0], b[j][1], tag))
-35
View File
@@ -1,35 +0,0 @@
import re, sys
def draws(p):
out = []
for line in open(p, encoding="utf8", errors="replace"):
m = re.search(r"n=(\d+) t=(\d+) ra=([0-9a-f]+)", line)
if m:
out.append((int(m.group(2)), m.group(3)))
return out
a = draws(sys.argv[1])
b = draws(sys.argv[2])
print("draws:", len(a), len(b))
n = min(len(a), len(b))
# compare caller sequence only (ignore tick stamps)
first_ra = None
for i in range(n):
if a[i][1] != b[i][1]:
first_ra = i
break
if first_ra is None:
print("CALLER SEQUENCE IDENTICAL over", n, "draws")
else:
print("first caller divergence at draw", first_ra)
for j in range(max(0, first_ra - 3), min(n, first_ra + 4)):
tag = "same" if a[j][1] == b[j][1] else "DIFF <=="
print(" [%d] A t=%4d ra=%s B t=%4d ra=%s %s"
% (j, a[j][0], a[j][1], b[j][0], b[j][1], tag))
# tick-stamp divergence count (pacing jitter)
t_diff = sum(1 for i in range(n) if a[i][0] != b[i][0])
print("draws with differing tick stamps:", t_diff, "of", n)
if n:
print("final tick: A t=%d B t=%d" % (a[-1][0], b[-1][0]))
View File
Whitespace-only changes.
-556
View File
@@ -1,556 +0,0 @@
#include <stdio.h>
#include "aicommands2.h"
extern u8 m_RunToBondPersistent[];
s32 chraiitemsize(u8 *AIList, s32 offset)
{
// matches only as u8* despite text evidence of ai->val structs
switch (AIList[offset])
{
// Cant Use CMD Builder due to different order...
#if defined(USECMDBUILDER)
#ifndef _SYNHILITE
#define _AI_CMD(CMD) /* \
*/ \
case CAT(AI_, CMDNAME): /* \
*/ \
return CAT(CAT(AI_, CMDNAME), _LENGTH);
#define _AI_DEBUG()
#define _AI_CMD_POLYMORPH(CMD, A, P, Q, D)
#define DEFINE(x)
#include <aicommands.def>
#endif
#endif
case AI_GotoNext:
return sizeof(AiGotoNextRecord);
case AI_GotoFirst:
return sizeof(AiGotoFirstRecord);
case AI_Label:
return sizeof(AiLabelRecord);
case AI_Yield:
return sizeof(AiYieldRecord);
case AI_EndList:
return sizeof(AiEndListRecord);
case AI_SetChrAiList:
return sizeof(AiSetChrAiListRecord);
case AI_SetReturnAiList:
return sizeof(AiSetReturnAiListRecord);
case AI_Return:
return sizeof(AiReturnRecord);
case AI_Stop:
return sizeof(AiStopRecord);
case AI_Kneel:
return sizeof(AiKneelRecord);
case AI_PlayAnimation:
return sizeof(AiPlayAnimationRecord);
case AI_IFPlayingAnimation:
return sizeof(AiIFPlayingAnimationRecord);
case AI_PointAtBond:
return sizeof(AiPointAtBondRecord);
case AI_LookSurprised:
return sizeof(AiLookSurprisedRecord);
case AI_TRYSidestepping:
return sizeof(AiTRYSidesteppingRecord);
case AI_TRYSideHopping:
return sizeof(AiTRYSideHoppingRecord);
case AI_TRYSideRunning:
return sizeof(AiTRYSideRunningRecord);
case AI_TRYFiringWalk:
return sizeof(AiTRYFiringWalkRecord);
case AI_TRYFiringRun:
return sizeof(AiTRYFiringRunRecord);
case AI_TRYFiringRoll:
return sizeof(AiTRYFiringRollRecord);
case AI_TRYFireOrAimAtTarget:
return sizeof(AiTRYFireOrAimAtTargetRecord);
case AI_TRYFireOrAimAtTargetKneel:
return sizeof(AiTRYFireOrAimAtTargetKneelRecord);
case AI_IFImFiring: /* enum = 232 despite following enum = 21 in the list */
return sizeof(AiIFImFiringRecord);
case AI_IFImFiringAndLockedForward: /* enum = 231 despite being followed by enum = 22 in the list */
return sizeof(AiIFImFiringAndLockedForwardRecord);
case AI_TRYFireOrAimAtTargetUpdate:
return sizeof(AiTRYFireOrAimAtTargetUpdateRecord);
case AI_TRYFacingTarget:
return sizeof(AiTRYFacingTargetRecord);
case AI_HitChrWithItem:
return sizeof(AiHitChrWithItemRecord);
case AI_ChrHitChr:
return sizeof(AiChrHitChrRecord);
case AI_TRYThrowingGrenade:
return sizeof(AiTRYThrowingGrenadeRecord);
case AI_TRYDroppingItem:
return sizeof(AiTRYDroppingItemRecord);
case AI_RunToPad:
return sizeof(AiRunToPadRecord);
case AI_RunToPadPreset:
return sizeof(AiRunToPadPresetRecord);
case AI_WalkToPad:
return sizeof(AiWalkToPadRecord);
case AI_SprintToPad:
return sizeof(AiSprintToPadRecord);
case AI_StartPatrol:
return sizeof(AiStartPatrolRecord);
case AI_Surrender:
return sizeof(AiSurrenderRecord);
case AI_RemoveMe:
return sizeof(AiRemoveMeRecord);
case AI_ChrRemoveInstant:
return sizeof(AiChrRemoveInstantRecord);
case AI_TRYTriggeringAlarmAtPad:
return sizeof(AiTRYTriggeringAlarmAtPadRecord);
case AI_AlarmOn:
return sizeof(AiAlarmOnRecord);
case AI_AlarmOff:
return sizeof(AiAlarmOffRecord);
case AI_TRYRunFromBond:
return sizeof(AiTRYRunFromBondRecord);
case AI_TRYRunToBond:
return sizeof(AiTRYRunToBondRecord);
case AI_TRYWalkToBond:
return sizeof(AiTRYWalkToBondRecord);
case AI_TRYSprintToBond:
return sizeof(AiTRYSprintToBondRecord);
case AI_TRYFindCover:
return sizeof(AiTRYFindCoverRecord);
case AI_TRYRunToChr:
return sizeof(AiTRYRunToChrRecord);
case AI_TRYWalkToChr:
return sizeof(AiTRYWalkToChrRecord);
case AI_TRYSprintToChr:
return sizeof(AiTRYSprintToChrRecord);
case AI_IFImOnPatrolOrStopped:
return sizeof(AiIFImOnPatrolOrStoppedRecord);
case AI_IFChrDyingOrDead:
return sizeof(AiIFChrDyingOrDeadRecord);
case AI_IFChrDoesNotExist:
return sizeof(AiIFChrDoesNotExistRecord);
case AI_IFISeeBond:
return sizeof(AiIFISeeBondRecord);
case AI_SetNewRandom:
return sizeof(AiSetNewRandomRecord);
case AI_IFRandomLessThan:
return sizeof(AiIFRandomLessThanRecord);
case AI_IFRandomGreaterThan:
return sizeof(AiIFRandomGreaterThanRecord);
case AI_IFICanHearAlarm:
return sizeof(AiIFICanHearAlarmRecord);
case AI_IFAlarmIsOn:
return sizeof(AiIFAlarmIsOnRecord);
case AI_IFGasIsLeaking:
return sizeof(AiIFGasIsLeakingRecord);
case AI_IFIHeardBond:
return sizeof(AiIFIHeardBondRecord);
case AI_IFISeeSomeoneShot:
return sizeof(AiIFISeeSomeoneShotRecord);
case AI_IFISeeSomeoneDie:
return sizeof(AiIFISeeSomeoneDieRecord);
case AI_IFICouldSeeBond:
return sizeof(AiIFICouldSeeBondRecord);
case AI_IFICouldSeeBondsStan:
return sizeof(AiIFICouldSeeBondsStanRecord);
case AI_IFIWasShotRecently:
return sizeof(AiIFIWasShotRecentlyRecord);
case AI_IFIHeardBondRecently:
return sizeof(AiIFIHeardBondRecentlyRecord);
case AI_IFImInRoomWithChr:
return sizeof(AiIFImInRoomWithChrRecord);
case AI_IFIveNotBeenSeen:
return sizeof(AiIFIveNotBeenSeenRecord);
case AI_IFImOnScreen:
return sizeof(AiIFImOnScreenRecord);
case AI_IFMyRoomIsOnScreen:
return sizeof(AiIFMyRoomIsOnScreenRecord);
case AI_IFRoomWithPadIsOnScreen:
return sizeof(AiIFRoomWithPadIsOnScreenRecord);
case AI_IFImTargetedByBond:
return sizeof(AiIFImTargetedByBondRecord);
case AI_IFBondMissedMe:
return sizeof(AiIFBondMissedMeRecord);
case AI_IFMyAngleToBondLessThan:
return sizeof(AiIFMyAngleToBondLessThanRecord);
case AI_IFMyAngleToBondGreaterThan:
return sizeof(AiIFMyAngleToBondGreaterThanRecord);
case AI_IFMyAngleFromBondLessThan:
return sizeof(AiIFMyAngleFromBondLessThanRecord);
case AI_IFMyAngleFromBondGreaterThan:
return sizeof(AiIFMyAngleFromBondGreaterThanRecord);
case AI_IFMyDistanceToBondLessThanDecimeter:
return sizeof(AiIFMyDistanceToBondLessThanDecimeterRecord);
case AI_IFMyDistanceToBondGreaterThanDecimeter:
return sizeof(AiIFMyDistanceToBondGreaterThanDecimeterRecord);
case AI_IFChrDistanceToPadLessThanDecimeter:
return sizeof(AiIFChrDistanceToPadLessThanDecimeterRecord);
case AI_IFChrDistanceToPadGreaterThanDecimeter:
return sizeof(AiIFChrDistanceToPadGreaterThanDecimeterRecord);
case AI_IFMyDistanceToChrLessThanDecimeter:
return sizeof(AiIFMyDistanceToChrLessThanDecimeterRecord);
case AI_IFMyDistanceToChrGreaterThanDecimeter:
return sizeof(AiIFMyDistanceToChrGreaterThanDecimeterRecord);
case AI_TRYSettingMyPresetToChrWithinDistanceDecimeter:
return sizeof(AiTRYSettingMyPresetToChrWithinDistanceDecimeterRecord);
case AI_IFBondDistanceToPadLessThanDecimeter:
return sizeof(AiIFBondDistanceToPadLessThanDecimeterRecord);
case AI_IFBondDistanceToPadGreaterThanDecimeter:
return sizeof(AiIFBondDistanceToPadGreaterThanDecimeterRecord);
case AI_IFChrInRoomWithPad:
return sizeof(AiIFChrInRoomWithPadRecord);
case AI_IFBondInRoomWithPad:
return sizeof(AiIFBondInRoomWithPadRecord);
case AI_IFBondCollectedObject:
return sizeof(AiIFBondCollectedObjectRecord);
case AI_IFKeyDropped:
return sizeof(AiIFKeyDroppedRecord);
case AI_IFItemIsAttachedToObject:
return sizeof(AiIFItemIsAttachedToObjectRecord);
case AI_IFBondHasItemEquipped:
return sizeof(AiIFBondHasItemEquippedRecord);
case AI_IFObjectExists:
return sizeof(AiIFObjectExistsRecord);
case AI_IFObjectNotDestroyed:
return sizeof(AiIFObjectNotDestroyedRecord);
case AI_IFObjectWasActivated:
return sizeof(AiIFObjectWasActivatedRecord);
case AI_IFBondUsedGadgetOnObject:
return sizeof(AiIFBondUsedGadgetOnObjectRecord);
case AI_ActivateObject:
return sizeof(AiActivateObjectRecord);
case AI_DestroyObject:
return sizeof(AiDestroyObjectRecord);
case AI_DropObject:
return sizeof(AiDropObjectRecord);
case AI_ChrDropAllConcealedItems:
return sizeof(AiChrDropAllConcealedItemsRecord);
case AI_ChrDropAllHeldItems:
return sizeof(AiChrDropAllHeldItemsRecord);
case AI_BondCollectObject:
return sizeof(AiBondCollectObjectRecord);
case AI_ChrEquipObject:
return sizeof(AiChrEquipObjectRecord);
case AI_MoveObject:
return sizeof(AiMoveObjectRecord);
case AI_DoorOpen:
return sizeof(AiDoorOpenRecord);
case AI_DoorClose:
return sizeof(AiDoorCloseRecord);
case AI_IFDoorStateEqual:
return sizeof(AiIFDoorStateEqualRecord);
case AI_IFDoorHasBeenOpenedBefore:
return sizeof(AiIFDoorHasBeenOpenedBeforeRecord);
case AI_DoorSetLock:
return sizeof(AiDoorSetLockRecord);
case AI_DoorUnsetLock:
return sizeof(AiDoorUnsetLockRecord);
case AI_IFDoorLockEqual:
return sizeof(AiIFDoorLockEqualRecord);
case AI_IFObjectiveNumComplete:
return sizeof(AiIFObjectiveNumCompleteRecord);
case AI_TRYUnknown6e:
return sizeof(AiTRYUnknown6eRecord);
case AI_TRYUnknown6f:
return sizeof(AiTRYUnknown6fRecord);
case AI_IFGameDifficultyLessThan:
return sizeof(AiIFGameDifficultyLessThanRecord);
case AI_IFGameDifficultyGreaterThan:
return sizeof(AiIFGameDifficultyGreaterThanRecord);
case AI_IFMissionTimeLessThan:
return sizeof(AiIFMissionTimeLessThanRecord);
case AI_IFMissionTimeGreaterThan:
return sizeof(AiIFMissionTimeGreaterThanRecord);
case AI_IFSystemPowerTimeLessThan:
return sizeof(AiIFSystemPowerTimeLessThanRecord);
case AI_IFSystemPowerTimeGreaterThan:
return sizeof(AiIFSystemPowerTimeGreaterThanRecord);
case AI_IFLevelIdLessThan:
return sizeof(AiIFLevelIdLessThanRecord);
case AI_IFLevelIdGreaterThan:
return sizeof(AiIFLevelIdGreaterThanRecord);
case AI_IFMyNumArghsLessThan:
return sizeof(AiIFMyNumArghsLessThanRecord);
case AI_IFMyNumArghsGreaterThan:
return sizeof(AiIFMyNumArghsGreaterThanRecord);
case AI_IFMyNumCloseArghsLessThan:
return sizeof(AiIFMyNumCloseArghsLessThanRecord);
case AI_IFMyNumCloseArghsGreaterThan:
return sizeof(AiIFMyNumCloseArghsGreaterThanRecord);
case AI_IFChrHealthLessThan:
return sizeof(AiIFChrHealthLessThanRecord);
case AI_IFChrHealthGreaterThan:
return sizeof(AiIFChrHealthGreaterThanRecord);
case AI_IFChrWasDamagedSinceLastCheck:
return sizeof(AiIFChrWasDamagedSinceLastCheckRecord);
case AI_IFBondHealthLessThan:
return sizeof(AiIFBondHealthLessThanRecord);
case AI_IFBondHealthGreaterThan:
return sizeof(AiIFBondHealthGreaterThanRecord);
case AI_SetMyMorale:
return sizeof(AiSetMyMoraleRecord);
case AI_AddToMyMorale:
return sizeof(AiAddToMyMoraleRecord);
case AI_SubtractFromMyMorale:
return sizeof(AiSubtractFromMyMoraleRecord);
case AI_IFMyMoraleLessThan:
return sizeof(AiIFMyMoraleLessThanRecord);
case AI_IFMyMoraleLessThanRandom:
return sizeof(AiIFMyMoraleLessThanRandomRecord);
case AI_SetMyAlertness:
return sizeof(AiSetMyAlertnessRecord);
case AI_AddToMyAlertness:
return sizeof(AiAddToMyAlertnessRecord);
case AI_SubtractFromMyAlertness:
return sizeof(AiSubtractFromMyAlertnessRecord);
case AI_IFMyAlertnessLessThan:
return sizeof(AiIFMyAlertnessLessThanRecord);
case AI_IFMyAlertnessLessThanRandom:
return sizeof(AiIFMyAlertnessLessThanRandomRecord);
case AI_SetMyHearingScale:
return sizeof(AiSetMyHearingScaleRecord);
case AI_SetMyVisionRange:
return sizeof(AiSetMyVisionRangeRecord);
case AI_SetMyGrenadeProbability:
return sizeof(AiSetMyGrenadeProbabilityRecord);
case AI_SetMyChrNum:
return sizeof(AiSetMyChrNumRecord);
case AI_SetMyHealthTotal:
return sizeof(AiSetMyHealthTotalRecord);
case AI_SetMyArmour:
return sizeof(AiSetMyArmourRecord);
case AI_SetMySpeedRating:
return sizeof(AiSetMySpeedRatingRecord);
case AI_SetMyArghRating:
return sizeof(AiSetMyArghRatingRecord);
case AI_SetMyAccuracyRating:
return sizeof(AiSetMyAccuracyRatingRecord);
case AI_SetMyFlags2:
return sizeof(AiSetMyFlags2Record);
case AI_UnsetMyFlags2:
return sizeof(AiUnsetMyFlags2Record);
case AI_IFMyFlags2Has:
return sizeof(AiIFMyFlags2HasRecord);
case AI_SetChrBitfield:
return sizeof(AiSetChrBitfieldRecord);
case AI_UnsetChrBitfield:
return sizeof(AiUnsetChrBitfieldRecord);
case AI_IFChrBitfieldHas:
return sizeof(AiIFChrBitfieldHasRecord);
case AI_SetObjectiveBitfield:
return sizeof(AiSetObjectiveBitfieldRecord);
case AI_UnsetObjectiveBitfield:
return sizeof(AiUnsetObjectiveBitfieldRecord);
case AI_IFObjectiveBitfieldHas:
return sizeof(AiIFObjectiveBitfieldHasRecord);
case AI_SetMychrflags:
return sizeof(AiSetMychrflagsRecord);
case AI_UnsetMychrflags:
return sizeof(AiUnsetMychrflagsRecord);
case AI_IFMychrflagsHas:
return sizeof(AiIFMychrflagsHasRecord);
case AI_SetChrchrflags:
return sizeof(AiSetChrchrflagsRecord);
case AI_UnsetChrchrflags:
return sizeof(AiUnsetChrchrflagsRecord);
case AI_IFChrchrflagsHas:
return sizeof(AiIFChrchrflagsHasRecord);
case AI_SetObjectFlags:
return sizeof(AiSetObjectFlagsRecord);
case AI_UnsetObjectFlags:
return sizeof(AiUnsetObjectFlagsRecord);
case AI_IFObjectFlagsHas:
return sizeof(AiIFObjectFlagsHasRecord);
case AI_SetObjectFlags2:
return sizeof(AiSetObjectFlags2Record);
case AI_UnsetObjectFlags2:
return sizeof(AiUnsetObjectFlags2Record);
case AI_IFObjectFlags2Has:
return sizeof(AiIFObjectFlags2HasRecord);
case AI_SetMyChrPreset:
return sizeof(AiSetMyChrPresetRecord);
case AI_SetChrChrPreset:
return sizeof(AiSetChrChrPresetRecord);
case AI_SetMyPadPreset:
return sizeof(AiSetMyPadPresetRecord);
case AI_SetChrPadPreset:
return sizeof(AiSetChrPadPresetRecord);
case AI_MyTimerStart:
return sizeof(AiMyTimerStartRecord);
case AI_MyTimerReset:
return sizeof(AiMyTimerResetRecord);
case AI_MyTimerPause:
return sizeof(AiMyTimerPauseRecord);
case AI_MyTimerResume:
return sizeof(AiMyTimerResumeRecord);
case AI_IFMyTimerIsNotRunning:
return sizeof(AiIFMyTimerIsNotRunningRecord);
case AI_IFMyTimerLessThanTicks:
return sizeof(AiIFMyTimerLessThanTicksRecord);
case AI_IFMyTimerGreaterThanTicks:
return sizeof(AiIFMyTimerGreaterThanTicksRecord);
case AI_HudCountdownShow:
return sizeof(AiHudCountdownShowRecord);
case AI_HudCountdownHide:
return sizeof(AiHudCountdownHideRecord);
case AI_HudCountdownSet:
return sizeof(AiHudCountdownSetRecord);
case AI_HudCountdownStop:
return sizeof(AiHudCountdownStopRecord);
case AI_HudCountdownStart:
return sizeof(AiHudCountdownStartRecord);
case AI_IFHudCountdownIsNotRunning:
return sizeof(AiIFHudCountdownIsNotRunningRecord);
case AI_IFHudCountdownLessThan:
return sizeof(AiIFHudCountdownLessThanRecord);
case AI_IFHudCountdownGreaterThan:
return sizeof(AiIFHudCountdownGreaterThanRecord);
case AI_TRYSpawningChrAtPad:
return sizeof(AiTRYSpawningChrAtPadRecord);
case AI_TRYSpawningChrNextToChr:
return sizeof(AiTRYSpawningChrNextToChrRecord);
case AI_TRYGiveMeItem:
return sizeof(AiTRYGiveMeItemRecord);
case AI_TRYGiveMeHat:
return sizeof(AiTRYGiveMeHatRecord);
case AI_TRYCloningChr:
return sizeof(AiTRYCloningChrRecord);
case AI_TextPrintBottom:
return sizeof(AiTextPrintBottomRecord);
case AI_TextPrintTop:
return sizeof(AiTextPrintTopRecord);
case AI_SfxPlay:
return sizeof(AiSfxPlayRecord);
case AI_SfxEmitFromObject:
return sizeof(AiSfxEmitFromObjectRecord);
case AI_SfxEmitFromPad:
return sizeof(AiSfxEmitFromPadRecord);
case AI_SfxSetChannelVolume:
return sizeof(AiSfxSetChannelVolumeRecord);
case AI_SfxFadeChannelVolume:
return sizeof(AiSfxFadeChannelVolumeRecord);
case AI_SfxStopChannel:
return sizeof(AiSfxStopChannelRecord);
case AI_IFSfxChannelVolumeLessThan:
return sizeof(AiIFSfxChannelVolumeLessThanRecord);
case AI_VehicleStartPath:
return sizeof(AiVehicleStartPathRecord);
case AI_VehicleSpeed:
return sizeof(AiVehicleSpeedRecord);
case AI_AircraftRotorSpeed:
return sizeof(AiAircraftRotorSpeedRecord);
case AI_IFCameraIsInIntro:
return sizeof(AiIFCameraIsInIntroRecord);
case AI_IFCameraIsInBondSwirl:
return sizeof(AiIFCameraIsInBondSwirlRecord);
case AI_TvChangeScreenBank:
return sizeof(AiTvChangeScreenBankRecord);
case AI_IFBondInTank:
return sizeof(AiIFBondInTankRecord);
case AI_EndLevel:
return sizeof(AiEndLevelRecord);
case AI_CameraReturnToBond:
return sizeof(AiCameraReturnToBondRecord);
case AI_CameraLookAtBondFromPad:
return sizeof(AiCameraLookAtBondFromPadRecord);
case AI_CameraSwitch:
return sizeof(AiCameraSwitchRecord);
case AI_IFBondYPosLessThan:
return sizeof(AiIFBondYPosLessThanRecord);
case AI_BondDisableControl:
return sizeof(AiBondDisableControlRecord);
case AI_BondEnableControl:
return sizeof(AiBondEnableControlRecord);
case AI_TRYTeleportingChrToPad:
return sizeof(AiTRYTeleportingChrToPadRecord);
case AI_ScreenFadeToBlack:
return sizeof(AiScreenFadeToBlackRecord);
case AI_ScreenFadeFromBlack:
return sizeof(AiScreenFadeFromBlackRecord);
case AI_IFScreenFadeCompleted:
return sizeof(AiIFScreenFadeCompletedRecord);
case AI_HideAllChrs:
return sizeof(AiHideAllChrsRecord);
case AI_ShowAllChrs:
return sizeof(AiShowAllChrsRecord);
case AI_DoorOpenInstant:
return sizeof(AiDoorOpenInstantRecord);
case AI_ChrRemoveItemInHand:
return sizeof(AiChrRemoveItemInHandRecord);
case AI_IfNumberOfActivePlayersLessThan:
return sizeof(AiIfNumberOfActivePlayersLessThanRecord);
case AI_IFBondItemTotalAmmoLessThan:
return sizeof(AiIFBondItemTotalAmmoLessThanRecord);
case AI_BondEquipItem:
return sizeof(AiBondEquipItemRecord);
case AI_BondEquipItemCinema:
return sizeof(AiBondEquipItemCinemaRecord);
case AI_BondSetLockedVelocity:
return sizeof(AiBondSetLockedVelocityRecord);
case AI_IFObjectInRoomWithPad:
return sizeof(AiIFObjectInRoomWithPadRecord);
case AI_SwitchSky:
return sizeof(AiSwitchSkyRecord);
case AI_TriggerFadeAndExitLevelOnButtonPress:
return sizeof(AiTriggerFadeAndExitLevelOnButtonPressRecord);
case AI_IFBondIsDead:
return sizeof(AiIFBondIsDeadRecord);
case AI_BondDisableDamageAndPickups:
return sizeof(AiBondDisableDamageAndPickupsRecord);
case AI_BondHideWeapons:
return sizeof(AiBondHideWeaponsRecord);
case AI_CameraOrbitPad:
return sizeof(AiCameraOrbitPadRecord);
case AI_CreditsRoll:
return sizeof(AiCreditsRollRecord);
case AI_IFCreditsHasCompleted:
return sizeof(AiIFCreditsHasCompletedRecord);
case AI_IFObjectiveAllCompleted:
return sizeof(AiIFObjectiveAllCompletedRecord);
case AI_IFFolderActorIsEqual:
return sizeof(AiIFFolderActorIsEqualRecord);
case AI_IFBondDamageAndPickupsDisabled:
return sizeof(AiIFBondDamageAndPickupsDisabledRecord);
case AI_MusicPlaySlot:
return sizeof(AiMusicPlaySlotRecord);
case AI_MusicStopSlot:
return sizeof(AiMusicStopSlotRecord);
case AI_TriggerExplosionsAroundBond:
return sizeof(AiTriggerExplosionsAroundBondRecord);
case AI_IFKilledCiviliansGreaterThan:
return sizeof(AiIFKilledCiviliansGreaterThanRecord);
case AI_IFChrWasShotSinceLastCheck:
return sizeof(AiIFChrWasShotSinceLastCheckRecord);
case AI_BondKilledInAction:
return sizeof(AiBondKilledInActionRecord);
case AI_RaiseArms:
return sizeof(AiRaiseArmsRecord);
case AI_GasLeakAndFadeFog:
return sizeof(AiGasLeakAndFadeFogRecord);
case AI_ObjectRocketLaunch:
return sizeof(AiObjectRocketLaunchRecord);
case AI_PRINT:
{
s32 pos = offset + 1;
while (AIList[pos] != 0)
{
++pos;
}
return (pos - offset) + 1;
}
default:
#if defined(ENABLE_LOG)
osSyncPrintf("chraiitemsize: unknown type %d!\n", *AIList);
#endif
return 1;
}
}
int main(void){
s32 off = 0;
while (1) {
s32 sz = chraiitemsize(m_RunToBondPersistent, off);
if (sz <= 0 || off + sz > 512) { printf("!! bad size %d at +%d\n", sz, off); break; }
unsigned cmd = m_RunToBondPersistent[off];
if (cmd == AI_EndList) { printf("+%-4d ENDLIST (size %d)\n", off, sz); break; }
printf("+%-4d cmd=%-3u ", off, cmd);
for (int i=1;i<sz;i++) printf("%02x ", m_RunToBondPersistent[off+i]);
printf("\n");
off += sz;
}
return 0;
}
-549
View File
@@ -1,549 +0,0 @@
#include <stdio.h>
#include "aicommands2.h"
extern u8 m_RunToBondPersistent[];
s32 chraiitemsize(u8 *AIList, s32 offset)
{
// matches only as u8* despite text evidence of ai->val structs
switch (AIList[offset])
{
// Cant Use CMD Builder due to different order...
#if defined(USECMDBUILDER)
#ifndef _SYNHILITE
#define _AI_CMD(CMD) /* \
*/ \
case CAT(AI_, CMDNAME): /* \
*/ \
return CAT(CAT(AI_, CMDNAME), _LENGTH);
#define _AI_DEBUG()
#define _AI_CMD_POLYMORPH(CMD, A, P, Q, D)
#define DEFINE(x)
#include <aicommands.def>
#endif
#endif
case AI_GotoNext:
return sizeof(AiGotoNextRecord);
case AI_GotoFirst:
return sizeof(AiGotoFirstRecord);
case AI_Label:
return sizeof(AiLabelRecord);
case AI_Yield:
return sizeof(AiYieldRecord);
case AI_EndList:
return sizeof(AiEndListRecord);
case AI_SetChrAiList:
return sizeof(AiSetChrAiListRecord);
case AI_SetReturnAiList:
return sizeof(AiSetReturnAiListRecord);
case AI_Return:
return sizeof(AiReturnRecord);
case AI_Stop:
return sizeof(AiStopRecord);
case AI_Kneel:
return sizeof(AiKneelRecord);
case AI_PlayAnimation:
return sizeof(AiPlayAnimationRecord);
case AI_IFPlayingAnimation:
return sizeof(AiIFPlayingAnimationRecord);
case AI_PointAtBond:
return sizeof(AiPointAtBondRecord);
case AI_LookSurprised:
return sizeof(AiLookSurprisedRecord);
case AI_TRYSidestepping:
return sizeof(AiTRYSidesteppingRecord);
case AI_TRYSideHopping:
return sizeof(AiTRYSideHoppingRecord);
case AI_TRYSideRunning:
return sizeof(AiTRYSideRunningRecord);
case AI_TRYFiringWalk:
return sizeof(AiTRYFiringWalkRecord);
case AI_TRYFiringRun:
return sizeof(AiTRYFiringRunRecord);
case AI_TRYFiringRoll:
return sizeof(AiTRYFiringRollRecord);
case AI_TRYFireOrAimAtTarget:
return sizeof(AiTRYFireOrAimAtTargetRecord);
case AI_TRYFireOrAimAtTargetKneel:
return sizeof(AiTRYFireOrAimAtTargetKneelRecord);
case AI_IFImFiring: /* enum = 232 despite following enum = 21 in the list */
return sizeof(AiIFImFiringRecord);
case AI_IFImFiringAndLockedForward: /* enum = 231 despite being followed by enum = 22 in the list */
return sizeof(AiIFImFiringAndLockedForwardRecord);
case AI_TRYFireOrAimAtTargetUpdate:
return sizeof(AiTRYFireOrAimAtTargetUpdateRecord);
case AI_TRYFacingTarget:
return sizeof(AiTRYFacingTargetRecord);
case AI_HitChrWithItem:
return sizeof(AiHitChrWithItemRecord);
case AI_ChrHitChr:
return sizeof(AiChrHitChrRecord);
case AI_TRYThrowingGrenade:
return sizeof(AiTRYThrowingGrenadeRecord);
case AI_TRYDroppingItem:
return sizeof(AiTRYDroppingItemRecord);
case AI_RunToPad:
return sizeof(AiRunToPadRecord);
case AI_RunToPadPreset:
return sizeof(AiRunToPadPresetRecord);
case AI_WalkToPad:
return sizeof(AiWalkToPadRecord);
case AI_SprintToPad:
return sizeof(AiSprintToPadRecord);
case AI_StartPatrol:
return sizeof(AiStartPatrolRecord);
case AI_Surrender:
return sizeof(AiSurrenderRecord);
case AI_RemoveMe:
return sizeof(AiRemoveMeRecord);
case AI_ChrRemoveInstant:
return sizeof(AiChrRemoveInstantRecord);
case AI_TRYTriggeringAlarmAtPad:
return sizeof(AiTRYTriggeringAlarmAtPadRecord);
case AI_AlarmOn:
return sizeof(AiAlarmOnRecord);
case AI_AlarmOff:
return sizeof(AiAlarmOffRecord);
case AI_TRYRunFromBond:
return sizeof(AiTRYRunFromBondRecord);
case AI_TRYRunToBond:
return sizeof(AiTRYRunToBondRecord);
case AI_TRYWalkToBond:
return sizeof(AiTRYWalkToBondRecord);
case AI_TRYSprintToBond:
return sizeof(AiTRYSprintToBondRecord);
case AI_TRYFindCover:
return sizeof(AiTRYFindCoverRecord);
case AI_TRYRunToChr:
return sizeof(AiTRYRunToChrRecord);
case AI_TRYWalkToChr:
return sizeof(AiTRYWalkToChrRecord);
case AI_TRYSprintToChr:
return sizeof(AiTRYSprintToChrRecord);
case AI_IFImOnPatrolOrStopped:
return sizeof(AiIFImOnPatrolOrStoppedRecord);
case AI_IFChrDyingOrDead:
return sizeof(AiIFChrDyingOrDeadRecord);
case AI_IFChrDoesNotExist:
return sizeof(AiIFChrDoesNotExistRecord);
case AI_IFISeeBond:
return sizeof(AiIFISeeBondRecord);
case AI_SetNewRandom:
return sizeof(AiSetNewRandomRecord);
case AI_IFRandomLessThan:
return sizeof(AiIFRandomLessThanRecord);
case AI_IFRandomGreaterThan:
return sizeof(AiIFRandomGreaterThanRecord);
case AI_IFICanHearAlarm:
return sizeof(AiIFICanHearAlarmRecord);
case AI_IFAlarmIsOn:
return sizeof(AiIFAlarmIsOnRecord);
case AI_IFGasIsLeaking:
return sizeof(AiIFGasIsLeakingRecord);
case AI_IFIHeardBond:
return sizeof(AiIFIHeardBondRecord);
case AI_IFISeeSomeoneShot:
return sizeof(AiIFISeeSomeoneShotRecord);
case AI_IFISeeSomeoneDie:
return sizeof(AiIFISeeSomeoneDieRecord);
case AI_IFICouldSeeBond:
return sizeof(AiIFICouldSeeBondRecord);
case AI_IFICouldSeeBondsStan:
return sizeof(AiIFICouldSeeBondsStanRecord);
case AI_IFIWasShotRecently:
return sizeof(AiIFIWasShotRecentlyRecord);
case AI_IFIHeardBondRecently:
return sizeof(AiIFIHeardBondRecentlyRecord);
case AI_IFImInRoomWithChr:
return sizeof(AiIFImInRoomWithChrRecord);
case AI_IFIveNotBeenSeen:
return sizeof(AiIFIveNotBeenSeenRecord);
case AI_IFImOnScreen:
return sizeof(AiIFImOnScreenRecord);
case AI_IFMyRoomIsOnScreen:
return sizeof(AiIFMyRoomIsOnScreenRecord);
case AI_IFRoomWithPadIsOnScreen:
return sizeof(AiIFRoomWithPadIsOnScreenRecord);
case AI_IFImTargetedByBond:
return sizeof(AiIFImTargetedByBondRecord);
case AI_IFBondMissedMe:
return sizeof(AiIFBondMissedMeRecord);
case AI_IFMyAngleToBondLessThan:
return sizeof(AiIFMyAngleToBondLessThanRecord);
case AI_IFMyAngleToBondGreaterThan:
return sizeof(AiIFMyAngleToBondGreaterThanRecord);
case AI_IFMyAngleFromBondLessThan:
return sizeof(AiIFMyAngleFromBondLessThanRecord);
case AI_IFMyAngleFromBondGreaterThan:
return sizeof(AiIFMyAngleFromBondGreaterThanRecord);
case AI_IFMyDistanceToBondLessThanDecimeter:
return sizeof(AiIFMyDistanceToBondLessThanDecimeterRecord);
case AI_IFMyDistanceToBondGreaterThanDecimeter:
return sizeof(AiIFMyDistanceToBondGreaterThanDecimeterRecord);
case AI_IFChrDistanceToPadLessThanDecimeter:
return sizeof(AiIFChrDistanceToPadLessThanDecimeterRecord);
case AI_IFChrDistanceToPadGreaterThanDecimeter:
return sizeof(AiIFChrDistanceToPadGreaterThanDecimeterRecord);
case AI_IFMyDistanceToChrLessThanDecimeter:
return sizeof(AiIFMyDistanceToChrLessThanDecimeterRecord);
case AI_IFMyDistanceToChrGreaterThanDecimeter:
return sizeof(AiIFMyDistanceToChrGreaterThanDecimeterRecord);
case AI_TRYSettingMyPresetToChrWithinDistanceDecimeter:
return sizeof(AiTRYSettingMyPresetToChrWithinDistanceDecimeterRecord);
case AI_IFBondDistanceToPadLessThanDecimeter:
return sizeof(AiIFBondDistanceToPadLessThanDecimeterRecord);
case AI_IFBondDistanceToPadGreaterThanDecimeter:
return sizeof(AiIFBondDistanceToPadGreaterThanDecimeterRecord);
case AI_IFChrInRoomWithPad:
return sizeof(AiIFChrInRoomWithPadRecord);
case AI_IFBondInRoomWithPad:
return sizeof(AiIFBondInRoomWithPadRecord);
case AI_IFBondCollectedObject:
return sizeof(AiIFBondCollectedObjectRecord);
case AI_IFKeyDropped:
return sizeof(AiIFKeyDroppedRecord);
case AI_IFItemIsAttachedToObject:
return sizeof(AiIFItemIsAttachedToObjectRecord);
case AI_IFBondHasItemEquipped:
return sizeof(AiIFBondHasItemEquippedRecord);
case AI_IFObjectExists:
return sizeof(AiIFObjectExistsRecord);
case AI_IFObjectNotDestroyed:
return sizeof(AiIFObjectNotDestroyedRecord);
case AI_IFObjectWasActivated:
return sizeof(AiIFObjectWasActivatedRecord);
case AI_IFBondUsedGadgetOnObject:
return sizeof(AiIFBondUsedGadgetOnObjectRecord);
case AI_ActivateObject:
return sizeof(AiActivateObjectRecord);
case AI_DestroyObject:
return sizeof(AiDestroyObjectRecord);
case AI_DropObject:
return sizeof(AiDropObjectRecord);
case AI_ChrDropAllConcealedItems:
return sizeof(AiChrDropAllConcealedItemsRecord);
case AI_ChrDropAllHeldItems:
return sizeof(AiChrDropAllHeldItemsRecord);
case AI_BondCollectObject:
return sizeof(AiBondCollectObjectRecord);
case AI_ChrEquipObject:
return sizeof(AiChrEquipObjectRecord);
case AI_MoveObject:
return sizeof(AiMoveObjectRecord);
case AI_DoorOpen:
return sizeof(AiDoorOpenRecord);
case AI_DoorClose:
return sizeof(AiDoorCloseRecord);
case AI_IFDoorStateEqual:
return sizeof(AiIFDoorStateEqualRecord);
case AI_IFDoorHasBeenOpenedBefore:
return sizeof(AiIFDoorHasBeenOpenedBeforeRecord);
case AI_DoorSetLock:
return sizeof(AiDoorSetLockRecord);
case AI_DoorUnsetLock:
return sizeof(AiDoorUnsetLockRecord);
case AI_IFDoorLockEqual:
return sizeof(AiIFDoorLockEqualRecord);
case AI_IFObjectiveNumComplete:
return sizeof(AiIFObjectiveNumCompleteRecord);
case AI_TRYUnknown6e:
return sizeof(AiTRYUnknown6eRecord);
case AI_TRYUnknown6f:
return sizeof(AiTRYUnknown6fRecord);
case AI_IFGameDifficultyLessThan:
return sizeof(AiIFGameDifficultyLessThanRecord);
case AI_IFGameDifficultyGreaterThan:
return sizeof(AiIFGameDifficultyGreaterThanRecord);
case AI_IFMissionTimeLessThan:
return sizeof(AiIFMissionTimeLessThanRecord);
case AI_IFMissionTimeGreaterThan:
return sizeof(AiIFMissionTimeGreaterThanRecord);
case AI_IFSystemPowerTimeLessThan:
return sizeof(AiIFSystemPowerTimeLessThanRecord);
case AI_IFSystemPowerTimeGreaterThan:
return sizeof(AiIFSystemPowerTimeGreaterThanRecord);
case AI_IFLevelIdLessThan:
return sizeof(AiIFLevelIdLessThanRecord);
case AI_IFLevelIdGreaterThan:
return sizeof(AiIFLevelIdGreaterThanRecord);
case AI_IFMyNumArghsLessThan:
return sizeof(AiIFMyNumArghsLessThanRecord);
case AI_IFMyNumArghsGreaterThan:
return sizeof(AiIFMyNumArghsGreaterThanRecord);
case AI_IFMyNumCloseArghsLessThan:
return sizeof(AiIFMyNumCloseArghsLessThanRecord);
case AI_IFMyNumCloseArghsGreaterThan:
return sizeof(AiIFMyNumCloseArghsGreaterThanRecord);
case AI_IFChrHealthLessThan:
return sizeof(AiIFChrHealthLessThanRecord);
case AI_IFChrHealthGreaterThan:
return sizeof(AiIFChrHealthGreaterThanRecord);
case AI_IFChrWasDamagedSinceLastCheck:
return sizeof(AiIFChrWasDamagedSinceLastCheckRecord);
case AI_IFBondHealthLessThan:
return sizeof(AiIFBondHealthLessThanRecord);
case AI_IFBondHealthGreaterThan:
return sizeof(AiIFBondHealthGreaterThanRecord);
case AI_SetMyMorale:
return sizeof(AiSetMyMoraleRecord);
case AI_AddToMyMorale:
return sizeof(AiAddToMyMoraleRecord);
case AI_SubtractFromMyMorale:
return sizeof(AiSubtractFromMyMoraleRecord);
case AI_IFMyMoraleLessThan:
return sizeof(AiIFMyMoraleLessThanRecord);
case AI_IFMyMoraleLessThanRandom:
return sizeof(AiIFMyMoraleLessThanRandomRecord);
case AI_SetMyAlertness:
return sizeof(AiSetMyAlertnessRecord);
case AI_AddToMyAlertness:
return sizeof(AiAddToMyAlertnessRecord);
case AI_SubtractFromMyAlertness:
return sizeof(AiSubtractFromMyAlertnessRecord);
case AI_IFMyAlertnessLessThan:
return sizeof(AiIFMyAlertnessLessThanRecord);
case AI_IFMyAlertnessLessThanRandom:
return sizeof(AiIFMyAlertnessLessThanRandomRecord);
case AI_SetMyHearingScale:
return sizeof(AiSetMyHearingScaleRecord);
case AI_SetMyVisionRange:
return sizeof(AiSetMyVisionRangeRecord);
case AI_SetMyGrenadeProbability:
return sizeof(AiSetMyGrenadeProbabilityRecord);
case AI_SetMyChrNum:
return sizeof(AiSetMyChrNumRecord);
case AI_SetMyHealthTotal:
return sizeof(AiSetMyHealthTotalRecord);
case AI_SetMyArmour:
return sizeof(AiSetMyArmourRecord);
case AI_SetMySpeedRating:
return sizeof(AiSetMySpeedRatingRecord);
case AI_SetMyArghRating:
return sizeof(AiSetMyArghRatingRecord);
case AI_SetMyAccuracyRating:
return sizeof(AiSetMyAccuracyRatingRecord);
case AI_SetMyFlags2:
return sizeof(AiSetMyFlags2Record);
case AI_UnsetMyFlags2:
return sizeof(AiUnsetMyFlags2Record);
case AI_IFMyFlags2Has:
return sizeof(AiIFMyFlags2HasRecord);
case AI_SetChrBitfield:
return sizeof(AiSetChrBitfieldRecord);
case AI_UnsetChrBitfield:
return sizeof(AiUnsetChrBitfieldRecord);
case AI_IFChrBitfieldHas:
return sizeof(AiIFChrBitfieldHasRecord);
case AI_SetObjectiveBitfield:
return sizeof(AiSetObjectiveBitfieldRecord);
case AI_UnsetObjectiveBitfield:
return sizeof(AiUnsetObjectiveBitfieldRecord);
case AI_IFObjectiveBitfieldHas:
return sizeof(AiIFObjectiveBitfieldHasRecord);
case AI_SetMychrflags:
return sizeof(AiSetMychrflagsRecord);
case AI_UnsetMychrflags:
return sizeof(AiUnsetMychrflagsRecord);
case AI_IFMychrflagsHas:
return sizeof(AiIFMychrflagsHasRecord);
case AI_SetChrchrflags:
return sizeof(AiSetChrchrflagsRecord);
case AI_UnsetChrchrflags:
return sizeof(AiUnsetChrchrflagsRecord);
case AI_IFChrchrflagsHas:
return sizeof(AiIFChrchrflagsHasRecord);
case AI_SetObjectFlags:
return sizeof(AiSetObjectFlagsRecord);
case AI_UnsetObjectFlags:
return sizeof(AiUnsetObjectFlagsRecord);
case AI_IFObjectFlagsHas:
return sizeof(AiIFObjectFlagsHasRecord);
case AI_SetObjectFlags2:
return sizeof(AiSetObjectFlags2Record);
case AI_UnsetObjectFlags2:
return sizeof(AiUnsetObjectFlags2Record);
case AI_IFObjectFlags2Has:
return sizeof(AiIFObjectFlags2HasRecord);
case AI_SetMyChrPreset:
return sizeof(AiSetMyChrPresetRecord);
case AI_SetChrChrPreset:
return sizeof(AiSetChrChrPresetRecord);
case AI_SetMyPadPreset:
return sizeof(AiSetMyPadPresetRecord);
case AI_SetChrPadPreset:
return sizeof(AiSetChrPadPresetRecord);
case AI_MyTimerStart:
return sizeof(AiMyTimerStartRecord);
case AI_MyTimerReset:
return sizeof(AiMyTimerResetRecord);
case AI_MyTimerPause:
return sizeof(AiMyTimerPauseRecord);
case AI_MyTimerResume:
return sizeof(AiMyTimerResumeRecord);
case AI_IFMyTimerIsNotRunning:
return sizeof(AiIFMyTimerIsNotRunningRecord);
case AI_IFMyTimerLessThanTicks:
return sizeof(AiIFMyTimerLessThanTicksRecord);
case AI_IFMyTimerGreaterThanTicks:
return sizeof(AiIFMyTimerGreaterThanTicksRecord);
case AI_HudCountdownShow:
return sizeof(AiHudCountdownShowRecord);
case AI_HudCountdownHide:
return sizeof(AiHudCountdownHideRecord);
case AI_HudCountdownSet:
return sizeof(AiHudCountdownSetRecord);
case AI_HudCountdownStop:
return sizeof(AiHudCountdownStopRecord);
case AI_HudCountdownStart:
return sizeof(AiHudCountdownStartRecord);
case AI_IFHudCountdownIsNotRunning:
return sizeof(AiIFHudCountdownIsNotRunningRecord);
case AI_IFHudCountdownLessThan:
return sizeof(AiIFHudCountdownLessThanRecord);
case AI_IFHudCountdownGreaterThan:
return sizeof(AiIFHudCountdownGreaterThanRecord);
case AI_TRYSpawningChrAtPad:
return sizeof(AiTRYSpawningChrAtPadRecord);
case AI_TRYSpawningChrNextToChr:
return sizeof(AiTRYSpawningChrNextToChrRecord);
case AI_TRYGiveMeItem:
return sizeof(AiTRYGiveMeItemRecord);
case AI_TRYGiveMeHat:
return sizeof(AiTRYGiveMeHatRecord);
case AI_TRYCloningChr:
return sizeof(AiTRYCloningChrRecord);
case AI_TextPrintBottom:
return sizeof(AiTextPrintBottomRecord);
case AI_TextPrintTop:
return sizeof(AiTextPrintTopRecord);
case AI_SfxPlay:
return sizeof(AiSfxPlayRecord);
case AI_SfxEmitFromObject:
return sizeof(AiSfxEmitFromObjectRecord);
case AI_SfxEmitFromPad:
return sizeof(AiSfxEmitFromPadRecord);
case AI_SfxSetChannelVolume:
return sizeof(AiSfxSetChannelVolumeRecord);
case AI_SfxFadeChannelVolume:
return sizeof(AiSfxFadeChannelVolumeRecord);
case AI_SfxStopChannel:
return sizeof(AiSfxStopChannelRecord);
case AI_IFSfxChannelVolumeLessThan:
return sizeof(AiIFSfxChannelVolumeLessThanRecord);
case AI_VehicleStartPath:
return sizeof(AiVehicleStartPathRecord);
case AI_VehicleSpeed:
return sizeof(AiVehicleSpeedRecord);
case AI_AircraftRotorSpeed:
return sizeof(AiAircraftRotorSpeedRecord);
case AI_IFCameraIsInIntro:
return sizeof(AiIFCameraIsInIntroRecord);
case AI_IFCameraIsInBondSwirl:
return sizeof(AiIFCameraIsInBondSwirlRecord);
case AI_TvChangeScreenBank:
return sizeof(AiTvChangeScreenBankRecord);
case AI_IFBondInTank:
return sizeof(AiIFBondInTankRecord);
case AI_EndLevel:
return sizeof(AiEndLevelRecord);
case AI_CameraReturnToBond:
return sizeof(AiCameraReturnToBondRecord);
case AI_CameraLookAtBondFromPad:
return sizeof(AiCameraLookAtBondFromPadRecord);
case AI_CameraSwitch:
return sizeof(AiCameraSwitchRecord);
case AI_IFBondYPosLessThan:
return sizeof(AiIFBondYPosLessThanRecord);
case AI_BondDisableControl:
return sizeof(AiBondDisableControlRecord);
case AI_BondEnableControl:
return sizeof(AiBondEnableControlRecord);
case AI_TRYTeleportingChrToPad:
return sizeof(AiTRYTeleportingChrToPadRecord);
case AI_ScreenFadeToBlack:
return sizeof(AiScreenFadeToBlackRecord);
case AI_ScreenFadeFromBlack:
return sizeof(AiScreenFadeFromBlackRecord);
case AI_IFScreenFadeCompleted:
return sizeof(AiIFScreenFadeCompletedRecord);
case AI_HideAllChrs:
return sizeof(AiHideAllChrsRecord);
case AI_ShowAllChrs:
return sizeof(AiShowAllChrsRecord);
case AI_DoorOpenInstant:
return sizeof(AiDoorOpenInstantRecord);
case AI_ChrRemoveItemInHand:
return sizeof(AiChrRemoveItemInHandRecord);
case AI_IfNumberOfActivePlayersLessThan:
return sizeof(AiIfNumberOfActivePlayersLessThanRecord);
case AI_IFBondItemTotalAmmoLessThan:
return sizeof(AiIFBondItemTotalAmmoLessThanRecord);
case AI_BondEquipItem:
return sizeof(AiBondEquipItemRecord);
case AI_BondEquipItemCinema:
return sizeof(AiBondEquipItemCinemaRecord);
case AI_BondSetLockedVelocity:
return sizeof(AiBondSetLockedVelocityRecord);
case AI_IFObjectInRoomWithPad:
return sizeof(AiIFObjectInRoomWithPadRecord);
case AI_SwitchSky:
return sizeof(AiSwitchSkyRecord);
case AI_TriggerFadeAndExitLevelOnButtonPress:
return sizeof(AiTriggerFadeAndExitLevelOnButtonPressRecord);
case AI_IFBondIsDead:
return sizeof(AiIFBondIsDeadRecord);
case AI_BondDisableDamageAndPickups:
return sizeof(AiBondDisableDamageAndPickupsRecord);
case AI_BondHideWeapons:
return sizeof(AiBondHideWeaponsRecord);
case AI_CameraOrbitPad:
return sizeof(AiCameraOrbitPadRecord);
case AI_CreditsRoll:
return sizeof(AiCreditsRollRecord);
case AI_IFCreditsHasCompleted:
return sizeof(AiIFCreditsHasCompletedRecord);
case AI_IFObjectiveAllCompleted:
return sizeof(AiIFObjectiveAllCompletedRecord);
case AI_IFFolderActorIsEqual:
return sizeof(AiIFFolderActorIsEqualRecord);
case AI_IFBondDamageAndPickupsDisabled:
return sizeof(AiIFBondDamageAndPickupsDisabledRecord);
case AI_MusicPlaySlot:
return sizeof(AiMusicPlaySlotRecord);
case AI_MusicStopSlot:
return sizeof(AiMusicStopSlotRecord);
case AI_TriggerExplosionsAroundBond:
return sizeof(AiTriggerExplosionsAroundBondRecord);
case AI_IFKilledCiviliansGreaterThan:
return sizeof(AiIFKilledCiviliansGreaterThanRecord);
case AI_IFChrWasShotSinceLastCheck:
return sizeof(AiIFChrWasShotSinceLastCheckRecord);
case AI_BondKilledInAction:
return sizeof(AiBondKilledInActionRecord);
case AI_RaiseArms:
return sizeof(AiRaiseArmsRecord);
case AI_GasLeakAndFadeFog:
return sizeof(AiGasLeakAndFadeFogRecord);
case AI_ObjectRocketLaunch:
return sizeof(AiObjectRocketLaunchRecord);
case AI_PRINT:
return 1; /* D309 candidate fix: PRINT is a 1-byte no-op record */
default:
#if defined(ENABLE_LOG)
osSyncPrintf("chraiitemsize: unknown type %d!\n", *AIList);
#endif
return 1;
}
}
int main(void){
s32 off = 0;
while (1) {
s32 sz = chraiitemsize(m_RunToBondPersistent, off);
if (sz <= 0 || off + sz > 512) { printf("!! bad size %d at +%d\n", sz, off); break; }
unsigned cmd = m_RunToBondPersistent[off];
if (cmd == AI_EndList) { printf("+%-4d ENDLIST (size %d)\n", off, sz); break; }
printf("+%-4d cmd=%-3u ", off, cmd);
for (int i=1;i<sz;i++) printf("%02x ", m_RunToBondPersistent[off+i]);
printf("\n");
off += sz;
}
return 0;
}
-36
View File
@@ -1,36 +0,0 @@
[New Thread 35936.0x9b30]
[New Thread 35936.0xac8c]
[New Thread 35936.0xaea4]
[New Thread 35936.0x63cc]
[New Thread 35936.0x7e0c]
[New Thread 35936.0x23e4]
[New Thread 35936.0x3ecc]
[New Thread 35936.0xb1a8]
[New Thread 35936.0xb390]
[New Thread 35936.0xa984]
[New Thread 35936.0xa1ec]
[New Thread 35936.0xb190]
[New Thread 35936.0xa500]
[New Thread 35936.0x97b4]
[New Thread 35936.0x694]
0x14014f360 <m_RunToBondPersistent>: 0x02 0x28 0x28 0x1b 0xad 0x02 0x1b 0x03
0x14014f368 <m_RunToBondPersistent+8>: 0x3c 0x06 0x2f 0x02 0x01 0x1b 0x02 0x01
0x14014f370 <m_RunToBondPersistent+16>: 0x03 0x78 0x06 0x2d 0x9f 0x00 0x00 0x00
0x14014f378 <m_RunToBondPersistent+24>: 0x10 0x2f 0x02 0x2d 0x2f 0x06 0x4c 0x00
0x14014f380 <m_RunToBondPersistent+32>: 0xc8 0x03 0x01 0x01 0x02 0x03 0x01 0x28
0x14014f388 <m_RunToBondPersistent+40>: 0x02 0x06 0x3c 0x03 0x00 0x02 0x02 0x24
0x14014f390 <m_RunToBondPersistent+48>: 0x03 0x4b 0x00 0x32 0x03 0x2f 0x03 0x01
0x14014f398 <m_RunToBondPersistent+56>: 0x28 0x02 0x03 0x9f 0x00 0x00 0x00 0x10
0x14014f3a0 <m_RunToBondPersistent+64>: 0x2f 0x02 0x2b 0x33 0x35 0x0a 0x03 0x1a
0x14014f3a8 <m_RunToBondPersistent+72>: 0x02 0x02 0x03 0x35 0x32 0x03 0x0e 0x02
0x14014f3b0 <m_RunToBondPersistent+80>: 0x02 0x03 0x35 0x3c 0x03 0x13 0x02 0x02
0x14014f3b8 <m_RunToBondPersistent+88>: 0x03 0x35 0x50 0x03 0x13 0x02 0x02 0x03
0x14014f3c0 <m_RunToBondPersistent+96>: 0x35 0x64 0x03 0x11 0x02 0x02 0x03 0x35
0x14014f3c8 <m_RunToBondPersistent+104>: 0x96 0x03 0x12 0x02 0x02 0x03 0x35 0xc8
0x14014f3d0 <m_RunToBondPersistent+112>: 0x03 0x14 0x00 0x01 0x00 0x00 0x02 0x02
0x14014f3d8 <m_RunToBondPersistent+120>: 0x03 0x15 0x00 0x01 0x00 0x00 0x02 0x02
0x14014f3e0 <m_RunToBondPersistent+128>: 0x02 0x3c 0x03 0x00 0x1b 0x02 0x1b 0x03
0x14014f3e8 <m_RunToBondPersistent+136>: 0x33 0x35 0xa0 0x03 0x00 0x1c 0x02 0x03
0x14014f3f0 <m_RunToBondPersistent+144>: 0x03 0x01 0x01 0x02 0x1c 0xae 0x28 0x1d
0x14014f3f8 <m_RunToBondPersistent+152>: 0x02 0x1d 0x03 0x2f 0x03 0xb4 0x00 0x00
[Inferior 1 (process 35936) detached]
-217
View File
@@ -1,217 +0,0 @@
[New Thread 35936.0x9b30]
[New Thread 35936.0xac8c]
[New Thread 35936.0xaea4]
[New Thread 35936.0x63cc]
[New Thread 35936.0x7e0c]
[New Thread 35936.0x23e4]
[New Thread 35936.0x3ecc]
[New Thread 35936.0xb1a8]
[New Thread 35936.0xb390]
[New Thread 35936.0xa984]
[New Thread 35936.0xa1ec]
[New Thread 35936.0xb190]
[New Thread 35936.0xa500]
[New Thread 35936.0x51b4]
Id Target Id Frame
1 Thread 35936.0x8228 0x00007ffb4facd781 in ntdll!RtlFindCharInUnicodeString () from C:\Windows\SYSTEM32\ntdll.dll
2 Thread 35936.0x9b30 0x00007ffb4fb4e104 in ntdll!ZwWaitForMultipleObjects () from C:\Windows\SYSTEM32\ntdll.dll
3 Thread 35936.0xac8c 0x00007ffb4fb4d634 in ntdll!ZwWaitForSingleObject () from C:\Windows\SYSTEM32\ntdll.dll
4 Thread 35936.0xaea4 0x00007ffb4d88a124 in win32u!NtUserMsgWaitForMultipleObjectsEx () from C:\Windows\System32\win32u.dll
5 Thread 35936.0x63cc "SDLAudioP2" 0x00007ffb4fb4d634 in ntdll!ZwWaitForSingleObject () from C:\Windows\SYSTEM32\ntdll.dll
6 Thread 35936.0x7e0c 0x00007ffb4fb4e104 in ntdll!ZwWaitForMultipleObjects () from C:\Windows\SYSTEM32\ntdll.dll
7 Thread 35936.0x23e4 0x00007ffb4fb4dc34 in ntdll!ZwDelayExecution () from C:\Windows\SYSTEM32\ntdll.dll
8 Thread 35936.0x3ecc 0x00007ffb4fb4dc34 in ntdll!ZwDelayExecution () from C:\Windows\SYSTEM32\ntdll.dll
9 Thread 35936.0xb1a8 0x000000014003a4dd in chraiitemsize (AIList=AIList@entry=0x14014f360 <m_RunToBondPersistent> "\002((\033­\002\033\003<\006/\002\001\033\002\001\003x\006-Ÿ", offset=offset@entry=133) at C:/Users/james/Source/Repos/gh-fullhist/src/game/chrai.c:162
10 Thread 35936.0xb390 0x00007ffb4fb4dc34 in ntdll!ZwDelayExecution () from C:\Windows\SYSTEM32\ntdll.dll
11 Thread 35936.0xa984 0x00007ffb4fb4e104 in ntdll!ZwWaitForMultipleObjects () from C:\Windows\SYSTEM32\ntdll.dll
12 Thread 35936.0xa1ec 0x00007ffb4fb4e104 in ntdll!ZwWaitForMultipleObjects () from C:\Windows\SYSTEM32\ntdll.dll
13 Thread 35936.0xb190 0x00007ffb4fb4d634 in ntdll!ZwWaitForSingleObject () from C:\Windows\SYSTEM32\ntdll.dll
14 Thread 35936.0xa500 0x00007ffb4fb51044 in ntdll!ZwWaitForWorkViaWorkerFactory () from C:\Windows\SYSTEM32\ntdll.dll
* 15 Thread 35936.0x51b4 0x00007ffb4fb510e1 in ntdll!DbgBreakPoint () from C:\Windows\SYSTEM32\ntdll.dll
Thread 15 (Thread 35936.0x51b4):
#0 0x00007ffb4fb510e1 in ntdll!DbgBreakPoint () from C:\Windows\SYSTEM32\ntdll.dll
#1 0x00007ffb4fb7cb3e in ntdll!DbgUiRemoteBreakin () from C:\Windows\SYSTEM32\ntdll.dll
#2 0x00007ffb4ed17384 in KERNEL32!BaseThreadInitThunk () from C:\Windows\System32\kernel32.dll
#3 0x00007ffb4fafcc91 in ntdll!RtlUserThreadStart () from C:\Windows\SYSTEM32\ntdll.dll
#4 0x0000000000000000 in ?? ()
Thread 14 (Thread 35936.0xa500):
#0 0x00007ffb4fb51044 in ntdll!ZwWaitForWorkViaWorkerFactory () from C:\Windows\SYSTEM32\ntdll.dll
#1 0x00007ffb4fafd407 in ntdll!TpReleaseCleanupGroupMembers () from C:\Windows\SYSTEM32\ntdll.dll
#2 0x00007ffb4ed17384 in KERNEL32!BaseThreadInitThunk () from C:\Windows\System32\kernel32.dll
#3 0x00007ffb4fafcc91 in ntdll!RtlUserThreadStart () from C:\Windows\SYSTEM32\ntdll.dll
#4 0x0000000000000000 in ?? ()
Thread 13 (Thread 35936.0xb190):
#0 0x00007ffb4fb4d634 in ntdll!ZwWaitForSingleObject () from C:\Windows\SYSTEM32\ntdll.dll
#1 0x00007ffb4d54b6ae in WaitForSingleObjectEx () from C:\Windows\System32\KernelBase.dll
#2 0x00007ff96823cd8a in nvoglv64!DrvValidateVersion () from C:\Windows\System32\DriverStore\FileRepository\nv_dispi.inf_amd64_b20cc8aeaed64fc2\nvoglv64.dll
#3 0x00007ff967fc0daa in ?? () from C:\Windows\System32\DriverStore\FileRepository\nv_dispi.inf_amd64_b20cc8aeaed64fc2\nvoglv64.dll
#4 0x00007ff967fc079e in ?? () from C:\Windows\System32\DriverStore\FileRepository\nv_dispi.inf_amd64_b20cc8aeaed64fc2\nvoglv64.dll
#5 0x00007ff96823ecc8 in nvoglv64!DrvValidateVersion () from C:\Windows\System32\DriverStore\FileRepository\nv_dispi.inf_amd64_b20cc8aeaed64fc2\nvoglv64.dll
#6 0x00007ffb4ed17384 in KERNEL32!BaseThreadInitThunk () from C:\Windows\System32\kernel32.dll
#7 0x00007ffb4fafcc91 in ntdll!RtlUserThreadStart () from C:\Windows\SYSTEM32\ntdll.dll
#8 0x0000000000000000 in ?? ()
Thread 12 (Thread 35936.0xa1ec):
#0 0x00007ffb4fb4e104 in ntdll!ZwWaitForMultipleObjects () from C:\Windows\SYSTEM32\ntdll.dll
#1 0x00007ffb4d580d10 in WaitForMultipleObjectsEx () from C:\Windows\System32\KernelBase.dll
#2 0x00007ffb4d580c0e in WaitForMultipleObjects () from C:\Windows\System32\KernelBase.dll
#3 0x00007ffb3070242a in ?? () from C:\Users\james\Desktop\ge007-v0.3.0-playtest\libwinpthread-1.dll
#4 0x00007ffb307026ed in ?? () from C:\Users\james\Desktop\ge007-v0.3.0-playtest\libwinpthread-1.dll
#5 0x00007ffb30702ec7 in ?? () from C:\Users\james\Desktop\ge007-v0.3.0-playtest\libwinpthread-1.dll
#6 0x00000001400e001b in osRecvMesg (mq=mq@entry=0x140289d18 <g_AudioManager+600>, msg=msg@entry=0x654afe18, flag=flag@entry=1) at C:/Users/james/Source/Repos/gh-fullhist/port/src/libultra.c:700
#7 0x000000014010c1f8 in amMain (arg=<optimized out>) at C:/Users/james/Source/Repos/gh-fullhist/src/audi.c:472
#8 0x00000001400e0de4 in portThreadWrapper (arg=0x140229f00 <g_pt+224>) at C:/Users/james/Source/Repos/gh-fullhist/port/src/libultra.c:386
#9 portThreadWrapper (arg=0x140229f00 <g_pt+224>) at C:/Users/james/Source/Repos/gh-fullhist/port/src/libultra.c:367
#10 0x00007ffb30706dad in ?? () from C:\Users\james\Desktop\ge007-v0.3.0-playtest\libwinpthread-1.dll
#11 0x00007ffb4e35af5a in msvcrt!_beginthreadex () from C:\Windows\System32\msvcrt.dll
#12 0x00007ffb4e35b02c in msvcrt!_endthreadex () from C:\Windows\System32\msvcrt.dll
#13 0x00007ffb4ed17384 in KERNEL32!BaseThreadInitThunk () from C:\Windows\System32\kernel32.dll
#14 0x00007ffb4fafcc91 in ntdll!RtlUserThreadStart () from C:\Windows\SYSTEM32\ntdll.dll
#15 0x0000000000000000 in ?? ()
Thread 11 (Thread 35936.0xa984):
#0 0x00007ffb4fb4e104 in ntdll!ZwWaitForMultipleObjects () from C:\Windows\SYSTEM32\ntdll.dll
#1 0x00007ffb4d580d10 in WaitForMultipleObjectsEx () from C:\Windows\System32\KernelBase.dll
#2 0x00007ffb4d580c0e in WaitForMultipleObjects () from C:\Windows\System32\KernelBase.dll
#3 0x00007ffb3070242a in ?? () from C:\Users\james\Desktop\ge007-v0.3.0-playtest\libwinpthread-1.dll
#4 0x00007ffb307026ed in ?? () from C:\Users\james\Desktop\ge007-v0.3.0-playtest\libwinpthread-1.dll
#5 0x00007ffb30702ec7 in ?? () from C:\Users\james\Desktop\ge007-v0.3.0-playtest\libwinpthread-1.dll
#6 0x00000001400e001b in osRecvMesg (mq=mq@entry=0x1402884c0 <os_scheduler+64>, msg=msg@entry=0x65cafe18, flag=flag@entry=1) at C:/Users/james/Source/Repos/gh-fullhist/port/src/libultra.c:700
#7 0x000000014010b692 in __scMain (arg=0x140288480 <os_scheduler>) at C:/Users/james/Source/Repos/gh-fullhist/src/sched.c:254
#8 0x00000001400e0de4 in portThreadWrapper (arg=0x140229ec8 <g_pt+168>) at C:/Users/james/Source/Repos/gh-fullhist/port/src/libultra.c:386
#9 portThreadWrapper (arg=0x140229ec8 <g_pt+168>) at C:/Users/james/Source/Repos/gh-fullhist/port/src/libultra.c:367
#10 0x00007ffb30706dad in ?? () from C:\Users\james\Desktop\ge007-v0.3.0-playtest\libwinpthread-1.dll
#11 0x00007ffb4e35af5a in msvcrt!_beginthreadex () from C:\Windows\System32\msvcrt.dll
#12 0x00007ffb4e35b02c in msvcrt!_endthreadex () from C:\Windows\System32\msvcrt.dll
#13 0x00007ffb4ed17384 in KERNEL32!BaseThreadInitThunk () from C:\Windows\System32\kernel32.dll
#14 0x00007ffb4fafcc91 in ntdll!RtlUserThreadStart () from C:\Windows\SYSTEM32\ntdll.dll
#15 0x0000000000000000 in ?? ()
Thread 10 (Thread 35936.0xb390):
#0 0x00007ffb4fb4dc34 in ntdll!ZwDelayExecution () from C:\Windows\SYSTEM32\ntdll.dll
#1 0x00007ffb4d5762de in SleepEx () from C:\Windows\System32\KernelBase.dll
#2 0x00000001400e0e2a in portThreadWrapper (arg=0x140229e58 <g_pt+56>) at C:/Users/james/Source/Repos/gh-fullhist/port/src/libultra.c:382
#3 0x00007ffb30706dad in ?? () from C:\Users\james\Desktop\ge007-v0.3.0-playtest\libwinpthread-1.dll
#4 0x00007ffb4e35af5a in msvcrt!_beginthreadex () from C:\Windows\System32\msvcrt.dll
#5 0x00007ffb4e35b02c in msvcrt!_endthreadex () from C:\Windows\System32\msvcrt.dll
#6 0x00007ffb4ed17384 in KERNEL32!BaseThreadInitThunk () from C:\Windows\System32\kernel32.dll
#7 0x00007ffb4fafcc91 in ntdll!RtlUserThreadStart () from C:\Windows\SYSTEM32\ntdll.dll
#8 0x0000000000000000 in ?? ()
Thread 9 (Thread 35936.0xb1a8):
#0 0x000000014003a4dd in chraiitemsize (AIList=AIList@entry=0x14014f360 <m_RunToBondPersistent> "\002((\033­\002\033\003<\006/\002\001\033\002\001\003x\006-Ÿ", offset=offset@entry=133) at C:/Users/james/Source/Repos/gh-fullhist/src/game/chrai.c:162
#1 0x000000014003d89a in chraiGoToLabel (AIList=0x14014f360 <m_RunToBondPersistent>, Offset=133, LabelNum=0 '\000') at C:/Users/james/Source/Repos/gh-fullhist/src/game/chrai.c:772
#2 ai (Entityp=Entityp@entry=0x701d0f60, EntityType=EntityType@entry=PROP_TYPE_CHR) at C:/Users/james/Source/Repos/gh-fullhist/src/game/chrai.c:928
#3 0x0000000140038799 in chrlvActionTick (self=self@entry=0x701d0f60) at C:/Users/james/Source/Repos/gh-fullhist/src/game/chraction.c:9445
#4 0x0000000140038a92 in chrlvActionTick (self=self@entry=0x701d0f60) at C:/Users/james/Source/Repos/gh-fullhist/src/game/chraction.c:9428
#5 0x0000000140026200 in chrTick (prop=prop@entry=0x1401ee680 <g_Props+23136>) at C:/Users/james/Source/Repos/gh-fullhist/src/game/chr.c:2504
#6 0x0000000140044450 in propsTick () at C:/Users/james/Source/Repos/gh-fullhist/src/game/chrprop.c:1946
#7 0x000000014007d60b in lvlRender (DL=DL@entry=0x700922e0) at C:/Users/james/Source/Repos/gh-fullhist/src/game/lv.c:791
#8 0x00000001401123da in bossMainloop () at C:/Users/james/Source/Repos/gh-fullhist/src/boss.c:633
#9 0x00000001401128ec in bossEntry () at C:/Users/james/Source/Repos/gh-fullhist/src/boss.c:315
#10 0x00000001400e0de4 in portThreadWrapper (arg=0x140229e20 <g_pt>) at C:/Users/james/Source/Repos/gh-fullhist/port/src/libultra.c:386
#11 portThreadWrapper (arg=0x140229e20 <g_pt>) at C:/Users/james/Source/Repos/gh-fullhist/port/src/libultra.c:367
#12 0x00007ffb30706dad in ?? () from C:\Users\james\Desktop\ge007-v0.3.0-playtest\libwinpthread-1.dll
#13 0x00007ffb4e35af5a in msvcrt!_beginthreadex () from C:\Windows\System32\msvcrt.dll
#14 0x00007ffb4e35b02c in msvcrt!_endthreadex () from C:\Windows\System32\msvcrt.dll
#15 0x00007ffb4ed17384 in KERNEL32!BaseThreadInitThunk () from C:\Windows\System32\kernel32.dll
#16 0x00007ffb4fafcc91 in ntdll!RtlUserThreadStart () from C:\Windows\SYSTEM32\ntdll.dll
#17 0x0000000000000000 in ?? ()
Thread 8 (Thread 35936.0x3ecc):
#0 0x00007ffb4fb4dc34 in ntdll!ZwDelayExecution () from C:\Windows\SYSTEM32\ntdll.dll
#1 0x00007ffb4d5762de in SleepEx () from C:\Windows\System32\KernelBase.dll
#2 0x00000001400dfe1f in portTickThread (arg=<optimized out>) at C:/Users/james/Source/Repos/gh-fullhist/port/src/libultra.c:305
#3 0x00007ffb30706dad in ?? () from C:\Users\james\Desktop\ge007-v0.3.0-playtest\libwinpthread-1.dll
#4 0x00007ffb4e35af5a in msvcrt!_beginthreadex () from C:\Windows\System32\msvcrt.dll
#5 0x00007ffb4e35b02c in msvcrt!_endthreadex () from C:\Windows\System32\msvcrt.dll
#6 0x00007ffb4ed17384 in KERNEL32!BaseThreadInitThunk () from C:\Windows\System32\kernel32.dll
#7 0x00007ffb4fafcc91 in ntdll!RtlUserThreadStart () from C:\Windows\SYSTEM32\ntdll.dll
#8 0x0000000000000000 in ?? ()
Thread 7 (Thread 35936.0x23e4):
#0 0x00007ffb4fb4dc34 in ntdll!ZwDelayExecution () from C:\Windows\SYSTEM32\ntdll.dll
#1 0x00007ffb4d5762de in SleepEx () from C:\Windows\System32\KernelBase.dll
#2 0x00007ffb4265d6e7 in Windows.Gaming.Input!DllGetClassObject () from C:\Windows\System32\Windows.Gaming.Input.dll
#3 0x00007ffb4265d54c in Windows.Gaming.Input!DllGetClassObject () from C:\Windows\System32\Windows.Gaming.Input.dll
#4 0x00007ffb4ed17384 in KERNEL32!BaseThreadInitThunk () from C:\Windows\System32\kernel32.dll
#5 0x00007ffb4fafcc91 in ntdll!RtlUserThreadStart () from C:\Windows\SYSTEM32\ntdll.dll
#6 0x0000000000000000 in ?? ()
Thread 6 (Thread 35936.0x7e0c):
#0 0x00007ffb4fb4e104 in ntdll!ZwWaitForMultipleObjects () from C:\Windows\SYSTEM32\ntdll.dll
#1 0x00007ffb4d580d10 in WaitForMultipleObjectsEx () from C:\Windows\System32\KernelBase.dll
#2 0x00007ffb46fa7ebf in CreateDispatcherQueueController () from C:\Windows\SYSTEM32\CoreMessaging.dll
#3 0x00007ffb46fa7ba9 in CreateDispatcherQueueController () from C:\Windows\SYSTEM32\CoreMessaging.dll
#4 0x00007ffb46fa7331 in CreateDispatcherQueueController () from C:\Windows\SYSTEM32\CoreMessaging.dll
#5 0x00007ffb46fa65b4 in CreateDispatcherQueueController () from C:\Windows\SYSTEM32\CoreMessaging.dll
#6 0x00007ffb46fa9d34 in CreateDispatcherQueueController () from C:\Windows\SYSTEM32\CoreMessaging.dll
#7 0x00007ffb46fa6a98 in CreateDispatcherQueueController () from C:\Windows\SYSTEM32\CoreMessaging.dll
#8 0x00007ffb46fde515 in CoreUICreateEx () from C:\Windows\SYSTEM32\CoreMessaging.dll
#9 0x00007ffb46fdd39b in CoreUICreateEx () from C:\Windows\SYSTEM32\CoreMessaging.dll
#10 0x00007ffb3fb625da in SetInputFocus () from C:\Windows\SYSTEM32\InputHost.dll
#11 0x00007ffb3fb66829 in InputHost!DllGetActivationFactory () from C:\Windows\SYSTEM32\InputHost.dll
#12 0x00007ffb4ed17384 in KERNEL32!BaseThreadInitThunk () from C:\Windows\System32\kernel32.dll
#13 0x00007ffb4fafcc91 in ntdll!RtlUserThreadStart () from C:\Windows\SYSTEM32\ntdll.dll
#14 0x0000000000000000 in ?? ()
Thread 5 (Thread 35936.0x63cc "SDLAudioP2"):
#0 0x00007ffb4fb4d634 in ntdll!ZwWaitForSingleObject () from C:\Windows\SYSTEM32\ntdll.dll
#1 0x00007ffb4d54b6ae in WaitForSingleObjectEx () from C:\Windows\System32\KernelBase.dll
#2 0x00007ffaa98bf65d in ?? () from C:\Users\james\Desktop\ge007-v0.3.0-playtest\SDL2.dll
#3 0x00007ffaa9754ddf in ?? () from C:\Users\james\Desktop\ge007-v0.3.0-playtest\SDL2.dll
#4 0x00007ffaa980a777 in ?? () from C:\Users\james\Desktop\ge007-v0.3.0-playtest\SDL2.dll
#5 0x00007ffaa98d2e6e in ?? () from C:\Users\james\Desktop\ge007-v0.3.0-playtest\SDL2.dll
#6 0x00007ffb4ed17384 in KERNEL32!BaseThreadInitThunk () from C:\Windows\System32\kernel32.dll
#7 0x00007ffb4fafcc91 in ntdll!RtlUserThreadStart () from C:\Windows\SYSTEM32\ntdll.dll
#8 0x0000000000000000 in ?? ()
Thread 4 (Thread 35936.0xaea4):
#0 0x00007ffb4d88a124 in win32u!NtUserMsgWaitForMultipleObjectsEx () from C:\Windows\System32\win32u.dll
#1 0x00007ffb4edf0c8e in USER32!MsgWaitForMultipleObjectsEx () from C:\Windows\System32\user32.dll
#2 0x00007ff96823528f in nvoglv64!DrvValidateVersion () from C:\Windows\System32\DriverStore\FileRepository\nv_dispi.inf_amd64_b20cc8aeaed64fc2\nvoglv64.dll
#3 0x00007ffb4ed17384 in KERNEL32!BaseThreadInitThunk () from C:\Windows\System32\kernel32.dll
#4 0x00007ffb4fafcc91 in ntdll!RtlUserThreadStart () from C:\Windows\SYSTEM32\ntdll.dll
#5 0x0000000000000000 in ?? ()
Thread 3 (Thread 35936.0xac8c):
#0 0x00007ffb4fb4d634 in ntdll!ZwWaitForSingleObject () from C:\Windows\SYSTEM32\ntdll.dll
#1 0x00007ffb4d54b6ae in WaitForSingleObjectEx () from C:\Windows\System32\KernelBase.dll
#2 0x00007ff96823cd8a in nvoglv64!DrvValidateVersion () from C:\Windows\System32\DriverStore\FileRepository\nv_dispi.inf_amd64_b20cc8aeaed64fc2\nvoglv64.dll
#3 0x00007ff967fc0daa in ?? () from C:\Windows\System32\DriverStore\FileRepository\nv_dispi.inf_amd64_b20cc8aeaed64fc2\nvoglv64.dll
#4 0x00007ff967fc079e in ?? () from C:\Windows\System32\DriverStore\FileRepository\nv_dispi.inf_amd64_b20cc8aeaed64fc2\nvoglv64.dll
#5 0x00007ff96823ecc8 in nvoglv64!DrvValidateVersion () from C:\Windows\System32\DriverStore\FileRepository\nv_dispi.inf_amd64_b20cc8aeaed64fc2\nvoglv64.dll
#6 0x00007ffb4ed17384 in KERNEL32!BaseThreadInitThunk () from C:\Windows\System32\kernel32.dll
#7 0x00007ffb4fafcc91 in ntdll!RtlUserThreadStart () from C:\Windows\SYSTEM32\ntdll.dll
#8 0x0000000000000000 in ?? ()
Thread 2 (Thread 35936.0x9b30):
#0 0x00007ffb4fb4e104 in ntdll!ZwWaitForMultipleObjects () from C:\Windows\SYSTEM32\ntdll.dll
#1 0x00007ffb4d580d10 in WaitForMultipleObjectsEx () from C:\Windows\System32\KernelBase.dll
#2 0x00007ffb4d580c0e in WaitForMultipleObjects () from C:\Windows\System32\KernelBase.dll
#3 0x00007ff968271597 in nvoglv64!DrvPresentBuffers () from C:\Windows\System32\DriverStore\FileRepository\nv_dispi.inf_amd64_b20cc8aeaed64fc2\nvoglv64.dll
#4 0x00007ff968270b18 in nvoglv64!DrvPresentBuffers () from C:\Windows\System32\DriverStore\FileRepository\nv_dispi.inf_amd64_b20cc8aeaed64fc2\nvoglv64.dll
#5 0x00007ffb4ed17384 in KERNEL32!BaseThreadInitThunk () from C:\Windows\System32\kernel32.dll
#6 0x00007ffb4fafcc91 in ntdll!RtlUserThreadStart () from C:\Windows\SYSTEM32\ntdll.dll
#7 0x0000000000000000 in ?? ()
Thread 1 (Thread 35936.0x8228):
#0 0x00007ffb4facd781 in ntdll!RtlFindCharInUnicodeString () from C:\Windows\SYSTEM32\ntdll.dll
#1 0x00007ffb4fb1a7b2 in ntdll!ApiSetQueryApiSetPresenceEx () from C:\Windows\SYSTEM32\ntdll.dll
#2 0x00007ffb4d59751f in KERNELBASE!IsApiSetImplemented () from C:\Windows\System32\KernelBase.dll
#3 0x00007ffb4edf13d2 in USER32!GetSystemMetrics () from C:\Windows\System32\user32.dll
#4 0x00007ffaa98f42a3 in ?? () from C:\Users\james\Desktop\ge007-v0.3.0-playtest\SDL2.dll
#5 0x00007ffaa97a624d in ?? () from C:\Users\james\Desktop\ge007-v0.3.0-playtest\SDL2.dll
#6 0x00007ffaa978a185 in ?? () from C:\Users\james\Desktop\ge007-v0.3.0-playtest\SDL2.dll
#7 0x00007ffaa978a8a5 in ?? () from C:\Users\james\Desktop\ge007-v0.3.0-playtest\SDL2.dll
#8 0x00000001400e99c8 in videoPumpEvents () at C:/Users/james/Source/Repos/gh-fullhist/port/src/video.c:537
#9 0x00000001400e15d5 in SDL_main (argc=<optimized out>, argv=<optimized out>) at C:/Users/james/Source/Repos/gh-fullhist/port/src/main.c:244
#10 0x0000000140115c9c in main_getcmdline ()
#11 0x0000000140001157 in __tmainCRTStartup () at D:/W/B/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:266
#12 0x00007ffb4ed17384 in KERNEL32!BaseThreadInitThunk () from C:\Windows\System32\kernel32.dll
#13 0x00007ffb4fafcc91 in ntdll!RtlUserThreadStart () from C:\Windows\SYSTEM32\ntdll.dll
#14 0x0000000000000000 in ?? ()
[Inferior 1 (process 35936) detached]
+26 -7
View File
@@ -3227,7 +3227,13 @@ void modelSetAnimFrame2WithChrStuff(Model *model, f32 framea, f32 frameb, f32 fr
{ {
frameb = (framea > -1.0e6f && framea < 1.0e6f) ? framea : 0.0f; frameb = (framea > -1.0e6f && framea < 1.0e6f) ? framea : 0.0f;
} }
/* D311: the original guard only validated frameb. If framea /* D311 (RULE-2-SIGNOFF 2026-09-19, release review: user approved
* retention as the stability-maximizing option; classified as a
* defensive guard against non-finite state in the same class as
* the accepted D156 guards -- it only fires on poison values that
* indicate an already-broken state, and snaps to a valid frame
* rather than altering any legitimate animation):
* the original guard only validated frameb. If framea
* (model->animframe1) is ALREADY poisoned, "frameb = framea" left * (model->animframe1) is ALREADY poisoned, "frameb = framea" left
* both garbage and floorFloatToInt saturated the two near-equal * both garbage and floorFloatToInt saturated the two near-equal
* huge floats to far-apart ints -- observed live in Caverns: * huge floats to far-apart ints -- observed live in Caverns:
@@ -3646,14 +3652,23 @@ void modelTickAnim(struct Model *model, s32 numticks, s32 update_chrstuff)
* a scripted animation restart; a restart landing while unkb0 is * a scripted animation restart; a restart landing while unkb0 is
* stale-nonzero divides by it using a mismatched unkac/animrate * stale-nonzero divides by it using a mismatched unkac/animrate
* pair from the previous animation, producing huge playspeed * pair from the previous animation, producing huge playspeed
* spikes (~388-410, vs. a legitimate max of ~2.0). This clamp is * spikes (~388-410, vs. a legitimate max of ~2.0).
* a stopgap for the symptom, not the root-cause fix.
* M-187: was mistakenly gated on d243mProbeActive() (requires * M-187: was mistakenly gated on d243mProbeActive() (requires
* GE_D243M=1), so it never fired for a real player -- only during * GE_D243M=1), so it never fired for a real player -- only during
* a diagnostic capture. Fixed to gate on the camera-mode test * a diagnostic capture. Fixed to gate on the camera-mode test
* alone (gameScriptedCameraActive()) so it's actually active by * alone (gameScriptedCameraActive()) so it's actually active by
* default. Logging stays separately gated on d243mProbeActive(). * default. Logging stays separately gated on d243mProbeActive().
* Threshold: 50.0 is way above any legitimate playspeed (normal * M-189 (2026-09-18) found and fixed the ACTUAL root cause (a
* stale hardcoded 32-bit sizeof(Model) literal in bondview2.c's
* model-carving buffer, user-verified live): this clamp no longer
* fires in practice. It is retained as defense-in-depth against
* any future out-of-range playspeed reaching a scripted camera.
* RULE-2-SIGNOFF (2026-09-19, release review): ungated
* behavior-modifying guard in src/game, approved for retention
* by the user as the stability-maximizing option for v0.3.0;
* candidate for removal post-release once all cutscenes are
* re-verified clean without it (findings.md D243 / M-192).
* Threshold: 10.0 is way above any legitimate playspeed (normal
* is ~1.0, max observed in gameplay is ~2.0). */ * is ~1.0, max observed in gameplay is ~2.0). */
extern int d243mProbeActive(void); extern int d243mProbeActive(void);
extern int gameScriptedCameraActive(void); extern int gameScriptedCameraActive(void);
@@ -3742,9 +3757,13 @@ void modelTickAnim(struct Model *model, s32 numticks, s32 update_chrstuff)
* range (0-1000) to prevent this. * range (0-1000) to prevent this.
* M-186 correction: NOT a D100/D140 struct-punning/pointer- * M-186 correction: NOT a D100/D140 struct-punning/pointer-
* widening issue -- see the M-183 comment above for the * widening issue -- see the M-183 comment above for the
* corrected mechanism (stale unkb0/unkb4/unkac/animrate on a * corrected mechanism and for M-189's actual root-cause fix
* scripted animation restart); this is a stopgap, not the root- * (stale 32-bit sizeof(Model) literal in bondview2.c); with that
* cause fix. * fix in place this clamp no longer fires in practice and is
* retained as defense-in-depth. RULE-2-SIGNOFF (2026-09-19,
* release review): approved for retention by the user for
* v0.3.0; candidate for removal post-release (findings.md D243 /
* M-192).
* M-187: was mistakenly gated on d243mProbeActive() (requires * M-187: was mistakenly gated on d243mProbeActive() (requires
* GE_D243M=1), so it never fired for a real player. Fixed to * GE_D243M=1), so it never fired for a real player. Fixed to
* gate on the camera-mode test alone (gameScriptedCameraActive()). * gate on the camera-mode test alone (gameScriptedCameraActive()).
+1 -1
View File
@@ -54,7 +54,7 @@ def one_liner(cell: str, limit: int = 160) -> str:
LEAD_RE = re.compile( LEAD_RE = re.compile(
r"^\**\s*(OPEN|RESOLVED|FIXED|PROPOSED|PARTIAL|LANDED|CLAMP|DISPROVEN" r"^\**\s*(OPEN|RESOLVED|FIXED|PROPOSED|PARTIAL|LANDED|CLAMP|DISPROVEN"
r"|ROOT-CAUSED|GUARDED|ANALYZED|DIAGNOSTIC SHIPPED|NOT A BUG)", r"|ROOT-CAUSED|GUARDED|ANALYZED|DIAGNOSTIC SHIPPED|NOT A BUG|CLOSED)",
re.I, re.I,
) )