Two pieces, and the first is the reason the second can be trusted. ps2.rs is the EE's FPU on raw u32 bit patterns. It is not f32: there are no denormals (exponent 0 *is* zero), no NaN and no infinity (exponent 255 is an ordinary value, so MAX reads back in Rust as NaN -- a test asserts exactly that, because it is the sharpest available statement of why this module exists), every result truncates toward zero, the adder discards the small operand's bits more than one below the large one's LSB and returns the large operand unchanged across a 25-bit exponent gap, and rsqrt is sqrt-then-divide with truncation between the steps rather than one rounded operation. The lighting pass accumulates all of these across every vertex of every patch, so this is a visible difference rather than a rounding curiosity. tfrag_light.rs is the pass itself: PEXT5 base colour, the select word picking one light set or blending two by bits 8..15 / 256, blended directions re-normalised where unblended ones are not, and base + A.rgb*max(dA, dA*wA) + B.rgb*max(dB, dB*wB). Lighting indexes positions, not vertex-info entries, since a common entry and a LOD entry can share a position. TfragLight gains a `select` field for the u16 at +6. It was briefly reconstructed with an unsafe pointer cast over the struct, which is exactly the sort of thing that breaks silently the moment a field is reordered; it is now a plainly parsed field. The pass does not run yet. The light bank framing the reference uses -- a u32 offset at +0x04, an i32 count there -- gives offset 0xa0d and a count of 698810368 on RAC2 level 0, so RAC2's gameplay extent is not laid out that way. The renderer now counts the vertices it actually lit and prints it, because falling back silently to the stored colours produces a plausible but wrong picture: lighting: 0 of 80274 vertices shaded by LightTfrags; the rest fall back to the tfrag's stored colours (no usable light bank) That line is the current honest state, and the frame has not changed as a result. Where RAC2 keeps its light bank is the open question.
40 lines
1.8 KiB
Rust
40 lines
1.8 KiB
Rust
//! The application: renderer, hardware models, and the frame loop.
|
|
//!
|
|
//! Reimplements the pieces of the PlayStation 2 that the game talks to, so the
|
|
//! game logic in `gc-game` can be written as ordinary Rust that draws and
|
|
//! sounds like the original.
|
|
//!
|
|
//! # Hardware being modelled
|
|
//!
|
|
//! * **Graphics Synthesizer (GS)** - fixed-function rasteriser. No shaders on
|
|
//! the real hardware: the GS does texture mapping, alpha and blend rules,
|
|
//! and z/stencil. Here that becomes wgpu plus explicit handling of the GS's
|
|
//! own rules (its `round(log2(z/n) + K)` mip selection, its blend and alpha
|
|
//! test behaviour, its alpha-0x80-is-1.0 convention).
|
|
//! * **VU0 / VU1** - vector units running microcode uploaded from the disc.
|
|
//! Skinning, lighting and transform setup live here. The microcode is
|
|
//! **binary** in the game's `.vutext` section, so it is reverse engineered
|
|
//! rather than parsed: this is the single hardest item in the project.
|
|
//! * **DMA and GIF/VIF packets** - the game streams geometry to the GS through
|
|
//! tag-split packet lists. Those packet formats are the input to rendering.
|
|
//! * **SPU2 / IOP** - audio and the disc interface, in `gc-video` and
|
|
//! `gc-extract` respectively.
|
|
//!
|
|
//! # Divergence from the first game
|
|
//!
|
|
//! R&C2's levels are spherical worlds, so camera, culling, fog and the sky are
|
|
//! all effectively rewritten compared with Ratchet & Clank (2002). Geometry
|
|
//! subsystems carry over in shape - `tfrag`, `tie`, `shrub`, `moby` are the
|
|
//! same four - but their behaviour on a sphere is new work.
|
|
//!
|
|
//! # Reference frame
|
|
//!
|
|
//! The port is validated against PCSX2 by replaying recorded input and
|
|
//! comparing frames. Without that loop, "looks close" and "is correct" drift
|
|
//! apart, and this game's difficulty and movement make that drift very
|
|
//! noticeable.
|
|
|
|
pub mod level;
|
|
pub mod ps2;
|
|
pub mod tfrag_light;
|