Commit Graph

169 Commits

Author SHA1 Message Date
Danshet 56c4e277b4 Unit-test the atomic write path (deterministic torn-write drill)
A crash cannot be unit-tested, but the disk state it leaves behind can. each failure point of the atomic write path: an abandoned temp, a death between the two commit renames, a stale write-in-progress marker, is constructed directly on disk and the recovery code asserted against it. The drill runs device-level without the game, deterministically.
2026-08-17 21:30:54 +02:00
Danshet 29e3dab140 Fix storage job submit-order race (ported from the title update)
The async save/DLC storage layer stores each job's operation code only after submitting it to the worker pool. Job objects are reused, so a fast worker reads the previous operation's code and performs the wrong storage operation. The retail title update reorders all twelve submit sites to store before the call. Hooks apply the same ordering to the base executable, engagement-logged. On the 360, core assignment made the window practically unhittable, but on the port, threading makes it real. Hottest during save-select and DLC content checks.
2026-08-17 21:29:17 +02:00
Danshet db76a8b671 Fix "Gamer Profile not selected" when the controller is not on the first slot
The game binds the player to the slot their controller enumerated on, and the recomp's single profile only answered on slot 0. A pad landing anywhere else made every sign-in query report "not signed in", producing the error. Behind ac6_profile_always_signed_in (default on), profile queries for slots 1-3 now answer with the one profile, so it follows the player to whichever slot their hardware landed on.
2026-08-17 21:24:25 +02:00
Danshet 939432b1e9 Log which user slot the game queries for sign-in state
The "Gamer Profile not selected" error is believed to come from the game binding the player to a controller that enumerated on slot 1-3 and then asking for that slot's sign-in state, which has no profile. One log line per distinct slot queried (plus one per XamShowSigninUI call recording what the sign-in layer did) makes an affected user's log settle it conclusively, at error level so default configurations capture it. No behavior change.
2026-08-17 21:23:17 +02:00
Danshet 0ec8de78df Quarantine content packages whose last write died mid-update instead of leaving them corrupt
Per-file atomic writes cannot cover a package half-updated across several files. The game's own integrity check then reports the data corrupted and asks the player to delete it. A marker now flags a package while writes are in flight, which when found again at the next mount, the package is moved aside to a quarantine folder (never deleted) with one log line, and the game recreates its data cleanly on the next run.
2026-08-17 21:21:55 +02:00
Danshet 7117b5b24a Make save and content writes atomic so an interrupted write cannot corrupt data
Overwriting a file through the content device used to delete the old file before the first new byte was written, so a crash or kill mid-save destroyed the existing data. A failed first-time save then left a half-written file the game reported as corrupted until it was deleted by hand. Writes now go to a temp file and commit by rename on close, keeping one .bak generation of the previous version. An interrupted write leaves the old data untouched, and a startup sweep resolves any write that died between the commit steps.
2026-08-17 21:18:49 +02:00
Danshet a0f1ca77dc Fix user_data_root and update_data_root being ignored in the config file
Both settings were consumed during startup before the config file was loaded, so a toml-set value arrived too late to matter and the game recreated its data tree in Documents regardless. Only through the command line or arguments worked. Path resolution now runs after config load, and command-line > toml > default precedence is made explicit rather than an accident of ordering, so a saved config can no longer override a command-line value (game_iso had the same latent hole).
2026-08-17 21:16:17 +02:00
Danshet 4d01457417 Fix the log file and path settings on non-ASCII install paths
Sweeps the config fix's defect class across the rest of the tree: the log file itself opened through the ANSI code page, the user_data_root/update_data_root/log_file settings, and both mod manifest loaders shared the same narrowing
2026-08-17 21:16:17 +02:00
Danshet ee5036e213 Fix settings not loading when the game is installed in a non-ASCII path
The config loader narrowed the toml path through the system ANSI code page while the parser expects UTF-8, so on Cyrillic/CJK/accented install paths the file silently failed to open and every setting fell back to defaults while saving worked fine, since the save path never narrowed. Loading now opens the file path-natively and parses the stream.
2026-08-17 21:13:24 +02:00
sal063 5d350c293a Update README.md 2026-08-12 16:19:31 +03:00
Dipshet ab90b54713 Render world effects (clouds/smoke/explosions) at scene resolution
AC6 renders its cloud/smoke/explosion chain into half-res buffers, which look
soft once the world is upscaled. Re-register those buffers at 1280x720 and 1x
instead of 640x360 and 4x MSAA, the same EDRAM tiles, so nothing downstream moves,
plus the pool reserve, compositor inputs and module viewport the enlarged chain
needs, and keep the fixed 2:1 silhouette downscaler at its native size so its
baked x2 cannot wrap. cvar: ac6_fullres_effects, off by default.
v1.0.0-beta.1
2026-08-09 21:12:03 +02:00
Dipshet 566817d628 Fix missing aircraft ground shadow on GPUs without constant-alpha blending (Blackwell and Battlemage)
The aircraft's ground shadow is drawn with the Xenos CONSTANT_ALPHA blend factors, which dfd8b92a routed to D3D12's ALPHA_FACTOR family, an OPTIONAL feature that must be checked via OPTIONS13::AlphaBlendFactorSupported first. We never checked, so on a device reporting false the shadow's pipeline is rejected and, being indistinguishable from one still compiling, its draw is dropped from every frame in silence. Now the capability is queried, and where it is absent the pixel shader carries the blend constant's alpha in its alpha output so INV_SRC_ALPHA reproduces the same blend exactly.
2026-08-09 19:36:57 +02:00
Dipshet 0164b919f8 Add support for loading unpacked DLCs from dlc/ folder 2026-08-09 16:32:26 +02:00
Dipshet 54e672720e Fix ultrawide not applying in Tutorial and Replay mode 2026-08-09 14:34:33 +02:00
Dipshet 51e6daa384 Fix default KBM bindings for missile and machine gun v1.0.0-beta 2026-08-09 02:19:56 +02:00
Dipshet cd21e7b3bb Set default show_build_stamp to false 2026-08-09 02:18:56 +02:00
Dipshet 9fae38a987 Updated README.md 2026-08-09 02:15:59 +02:00
Dipshet a353f9d7aa Write a crash report naming the guest instruction when the game dies
Any fatal event now writes one self-contained crash-<timestamp>.txt -
guest call stack, registers, a guest-versus-host verdict on the faulting
address, modules and the log tail naming rex_sub_* frames with no symbols.
2026-08-09 01:02:33 +02:00
Dipshet 98020a02b2 Fix lines on open waters seen at an acute angle (undefined shader derivatives)
The water shader's wave-normal lookup sits inside control flow this translator
generates from the guest's predication and jumps, where DXBC derivatives are
undefined: the gradient collapses to zero along the ocean mesh's seams, the LOD
clamps to the finest mip, and grazing Fresnel amplifies that into a bright line.
Computing the gradients in the prologue, where the quad is uniform, restores them.
2026-08-08 20:12:28 +02:00
Dipshet 07d09128e6 Silence the Alt+key system beep (unhandled WM_SYSCHAR)
While Alt is held every keypress arrives as WM_SYSKEYDOWN->WM_SYSCHAR,
and an unhandled WM_SYSCHAR reaching DefWindowProc on a menu-less
window triggers MessageBeep which causes camera panning on KB+M dinged constantly.
Consume it (and answer WM_MENUCHAR with MNC_CLOSE) when the window has
no menu.
2026-08-07 23:29:53 +02:00
Dipshet 42b6ab3b85 Hide the free cursor after idle (default 3 s)
Hide the free cursor after idle (ac6_cursor_hide_seconds, 3 s)
The free cursor now disappears after N seconds without motion and
returns instantly on motion or a button. Never hides while an overlay
is on screen (new DialogsVisible presence flag). Default 3 s, 0 = never, live.
2026-08-07 23:28:19 +02:00
Dipshet 4ca74fd107 Add keybind F11 to toggle fullscreen
Records the choice through the same user_value
path as a settings-menu edit.
2026-08-07 23:24:01 +02:00
Dipshet 90c1ef45ff HD terrain: draw the full shipped terrain resolution (ac6_terrain_hd, on)
The game ships 2x the terrain height samples it ever draws; its terrain
vertex shader is fully data-driven, so a synthetic full-density ring table
(vertex fetch constant 95 redirect) plus a matching fan emission make the
unmodified shader express every sample - no more terrain cracks ("rifts"),
true river beds.
2026-08-07 16:42:20 +02:00
Dipshet 93c6dba3ff Stop a controller disconnect/reconnect from closing the game
A failed SDL_OpenGamepad on hot-plug hit assert_always(), which is fatal in release: one transient open failure on reconnect closed the game.
The axis/button handlers also dereferenced the controller-index optional unchecked, so orphan pad events were UB -> std::terminate.
Now a failed open logs a WARN and returns; the pad retries on its next ADDED event. Orphan events are dropped with a rate-limited WARN.
2026-08-06 21:14:10 +02:00
Dipshet b0d9a067db Harden KB+M against OS-wedged keys: trust only observed up->down edges
GetAsyncKeyState can wedge "down" without a real press (Alt-Tab residue);
a phantom held Tab forwarded as held Y and killed the camera on both
keyboard and pad. Keys now count as held only after an observed up->down
since startup/focus gain.
2026-08-06 20:06:06 +02:00
Dipshet 667551d4c7 Fix KB+M going inert on the ground: heartbeat from every flight state
KB+M's flight heartbeat only came from the main force step, which never
runs on the ground, keyboard flight controls were dead until takeoff.
Fire it from every state's provider: the alternate ground step (rolling)
plus the master updates and ground-state maintainer (standstill).
2026-08-06 20:04:08 +02:00
Dipshet cf6000c0f6 Tag the WASAPI render stream GameEffects so media apps stop muting the game
Windows auto-mutes AudioCategory_GameMedia render streams whenever a Store media app (Screenbox, Windows' modern Media Player) plays music. Our single WASAPI stream carries the entire premixed game output, so the whole game fell silent. GameEffects is the category Windows games run as by default..
2026-08-06 18:29:44 +02:00
Dipshet 201a4038ea Revert "Guard XMA loop handling against degenerate loop metadata"
This reverts commit 466cac7c00.
The guard's reject test (loop_start >= loop_end) also matches a legitimate
"loop from start" encoding, so it suppressed real BGM metadata loops and
playback ran past the loop point.
2026-08-06 17:03:49 +02:00
Dipshet deb406bdb0 Fix cvar preset timing and settings-save leaks; tidy the cvar surface
Config presets now run after the toml loads: the ac6_fix_* switches and
their scale gates finally honor user settings. The settings save persists
only user-set values, with toml escaping - no leaked presets, and a saved
Windows path can no longer void the whole config. Runtime-forced values
(performance mode) can no longer overwrite the user's saved choices.
Menu: wrapped tooltips, "(set by <cvar>)" on driven entries, a developer
toggle; AC6-added cvars grouped under the AC6 node as AC6/Fixes and
AC6/Enhancements, with true restart/live lifecycles.
2026-08-06 15:46:15 +02:00
Dipshet 9b81d7b7e6 Mount the game from a .iso and DLC from raw containers directly
The game now mounts straight from a .iso beside the exe (selected by
title id; the assets folder still wins, and loose files layer over the
image so mods need no extraction), and DLC mounts straight from raw
STFS containers in a dlc folder, any layout, title updates ignored.
Disc image device ported from Xenia (BSD); one log line per source.
2026-08-06 02:37:42 +02:00
Dipshet 33c2cf60cc Fix overlay input leaking into the game: explicit input ownership
Interacting with the overlays also drove the game (clicks fired
weapons, scroll cycled them, keys leaked), and hovering one silenced a real
pad. Input now follows window-manager rules, mouse to the window under the
cursor, keyboard to the focused window, real pads never suppressed, via
ImGui capture flags conjoined with overlay visibility, published as atomics.
2026-08-06 00:43:34 +02:00
Dipshet 1d85960504 effect-mode fix: recognise CAce6EffectManager's draw slot
The two effect managers share the dispatcher slot but not the draw slot
(CX360 0x820B25D0, CAce6 0x822B0AD8); the fix only knew the first, so a
CAce6EffectManager job silently fell through to the unfixed path - the
diagnosed cause of the one flicker that survived field testing. Dispatch
both explicitly; count and warn on any unmodelled slot. Same cvar gate,
inert while ac6_effect_mode_fix is off.
2026-08-05 21:59:18 +02:00
Dipshet 9697710e43 Fix the one-frame effects/clouds flicker under host CPU pressure
The effect update and effect draw are two async worker-pool jobs entering
through one vtable slot, told apart only by a shared mode word with no
per-job copy; a host stall lets both jobs read "draw", so the effect and
cloud passes are emitted twice for one frame. Snapshot the mode at submit
and dispatch from the snapshot. Gated behind ac6_effect_mode_fix, default off.
2026-08-05 21:56:39 +02:00
Dipshet de2527ade5 Revert "Fix doubled cutscene dialogue: fold only the fronts while a cutscene plays"
This reverts commit edcb6314f2b1b06e70dbb214674eb7c2325f8ab1. The fold was a mitigation: the doubling was never in the assets but came from the decoder dropping straddled-header frames, letting the premix streams drift and comb. With the decode fixed at the root, the full summing fold is clean and cutscenes regain centre and rear content.
2026-08-05 20:31:37 +02:00
Dipshet 5ca3b24c62 apu: guard the XMA loop-end frame test against degenerate loop metadata
The loop-end test runs before UpdateLoopStatus, so the degenerate-loop guard there never reaches it. With loop_count > 0 and loop_start >= loop_end, the clamped loop end equals the start offset of the stream at packet 0, arming the frame output limit and silently truncating 384 samples from its first frame. Cvar audio_xma_loop_end_guard, default on.
2026-08-05 20:29:34 +02:00
Dipshet ad7be62321 apu: decode XMA frames whose 15-bit header straddles a packet boundary
The frame walk treated fewer than 15 remaining bits as end-of-chain, but a frame starting there is real: its header continues in the next packet, as the encoder's own seek ledger confirms. Each one was silently dropped, so a premix's parallel streams drifted apart in 512-sample steps and doubled on the fold. Cvar audio_xma_header_straddle_fix, on.
2026-08-05 20:26:02 +02:00
sal063 25486de692 Merge pull request #33 from Dipshet/fix-cutscene
Cutscene fixes: DoF at render scale, A/V resync after hitches, doubled dialogue
2026-07-31 11:42:20 +03:00
Dipshet edcb631442 Fix doubled cutscene dialogue: fold only the fronts while a cutscene plays
AC6's cutscene mixer submits its 5.1 premix to all six speaker slots as decorrelated near-copies of one mix; six real speakers separate them acoustically, but the port's 6→2 fold sums them, combing speech into the long-reported doubled dialogue. While the demo sequencer ticks, fold only the fronts (verified lossless). audio_cutscene_downmix (default on).
2026-07-31 04:25:30 +02:00
Dipshet 466cac7c00 Guard XMA loop handling against degenerate loop metadata
Streamed voices carrying degenerate loop metadata (loop_count 0xFF with loop_start == loop_end == 0) re-fired the loop machinery on every input buffer swap, truncating or skipping subframes of the stream. Require a real loop window (loop_start < loop_end, read_offset ≥ loop_end) before engaging, as in Xenia PR #1808. 47 confirmed fires in AC6; default on.
2026-07-31 04:24:07 +02:00
Dipshet 8c922abd77 Preserve the XMA stream timeline across undecodable frames
A frame the decoder backend rejects advances the read offset but emitted nothing, silently shortening that stream by 512 samples, permanent desync for multi-stream sources (5.1 premixes as parallel stereo XMA). Emit the frame as silence instead so the timeline holds. Robustness: no in-game trigger known in AC6. audio_xma_preserve_timeline (default on).
2026-07-31 04:23:20 +02:00
Dipshet b6b94bac91 Keep in-engine cutscene video locked to the audio clock after hitches
A render hitch during an in-engine cutscene permanently desynced video from the audio, which is master and keeps playing. Weak-symbol wrappers around the two demo-manager Exec functions issue bounded catch-up ticks computed from the audio clients' consumed-sample clock (48 kHz, deficit threshold 2). Behind ac6_cutscene_resync (on); dev tooling default-off.
2026-07-31 04:22:41 +02:00
Dipshet 23e463737c Fix cutscene depth-of-field striping and ghosting at render scale > 1
The cutscene DoF chain is authored for the 640×360 guest grid; at render scale > 1 its guest-granular blur kernels alias against host-granular content, visible as streaks and ghost outlines. Fix: snap the two CoC pre-blur passes to guest texel centers and densify the two 13-tap gather passes per axis. Hash-allowlisted, behind ac6_fix_dof (on), inert at 1x.
2026-07-31 03:58:29 +02:00
sal063 562ad5020a Merge pull request #32 from Dipshet/add-ultrawide
Add ultrawide support: hor+ in missions
2026-07-29 09:09:47 +03:00
Dipshet cc9d8aa54e Add ultrawide support: hor+ in missions
ac6_widescreen = true (default false), renders missions at the window's aspect ratio (hor+) by patching the game's per-camera aspect data, so FOV, culling and every camera follow. Menus, hangar, briefing and FMV revert to 16:9 and letterbox. The HUD is pre-squeezed at  draw time to stay crisp, and marker art is squared without moving the aim points. ac6_widescreen_cinematics enables it in in-game cutscenes(default true, gated).
2026-07-29 04:35:39 +02:00
sal063 3de677ef0d Merge pull request #31 from Dipshet/add-kbm
Add native KB+M support: menus, flight, mouse steering, pad-free play
2026-07-27 22:48:13 +03:00
Dipshet d35a8c8309 Add native KB+M support: menus, flight, mouse steering, pad-free play
Keyboard/mouse state is injected at the guest XamInput wrapper boundary, so
every layer of the input stack sees KB+M exactly as a connected pad, and a
real pad keeps working alongside. Menu and flight key sets (AC7-style
defaults) switch automatically via a flight-sim heartbeat; the mouse steers
pitch/roll with a velocity model, or pans the camera while the camera-control
key is held. With no controller connected, a synthetic pad is presented on
slot 0. Bindings and mouse feel live in ac6_input.toml (auto-created on first
run, hot-reloaded ~1x/s). Everything is off unless ac6_kbm_enabled is set.
2026-07-27 21:40:42 +02:00
sal063 c5b089fb69 Merge pull request #30 from Dipshet/fix-language
Fix Japanese language: honor console language/region config
2026-07-16 15:52:18 +03:00
Dipshet e44fc2266c Fix Japanese language: honor console language/region config
XGetLanguage and the XConfig language/country reads now follow the
user_language / user_country cvars instead of hardcoding English.
XGetGameRegion follows a new game_region cvar, defaulting to auto:
it reports 0x1FF when Japanese is selected, else region-free 0xFFFF.
Set user_language = 2 for full Japanese text and voice; defaults are unchanged for English.
2026-07-16 14:48:25 +02:00
sal063 ca90179a7a Merge pull request #28 from Dipshet/fix-shadows
D3D12: Fix CONSTANT_ALPHA blend factors collapsing onto constant RGB
2026-07-15 03:04:55 +03:00
Dipshet dfd8b92a5b D3D12: Fix CONSTANT_ALPHA blend factors collapsing onto constant RGB
The D3D12 PipelineBlendFactor enum had no constant-alpha entry, so the Xenos
CONSTANT_ALPHA and ONE_MINUS_CONSTANT_ALPHA blend factors (14, 15) were mapped
onto the constant-COLOR kBlendFactor / kInvBlendFactor - i.e. D3D12 BLEND_FACTOR
/ INV_BLEND_FACTOR, which use the blend constant's RGB rather than its alpha.

Aircraft ground shadow blends with dst = ONE_MINUS_CONSTANT_ALPHA and aSTANT_ALPHA blend factors collapsing onto
blend constant of (0.03, 0.04, 0.04, 0.30): it wants 1 - 0.30 = 0.70 (scale the
background down -> darken), but got 1 - (0.03,0.04,0.04) ~= 0.97 (barely scaled)
with the white source added on top, so the shadow BRIGHTENED instead of
darkening - the "white shadow" bug. Vulkan has the distinct
ONE_MINUS_CONSTANT_ALPHA factor and renders it correctly.

Add kBlendFactorAlpha / kInvBlendFactorAlpha to the enum, route factors 14/15 to
them in both the colour and alpha maps, and map them to D3D12 ALPHA_FACTOR /
INV_ALPHA_FACTOR. Verified fixed on both the RTV and ROV render-target paths.
2026-07-15 02:03:35 +02:00