fix(game): restore six-state target rotation

Replace the free-running 68x60 wheel animation with the original six-callback
91x90 DAT600 mechanism. Start WAVE 2011 at state one, advance once per selected
detail timer, and rotate the five per-player lock contact/item values exactly at
state six.

Decode the 17x17 DAT600 target image/mask pair and render all six recovered
position sets over the correct atlas or overlay-B base. Preserve filled targets
in their resting state after rotation and add a deterministic `targets` scenario
for trace and framebuffer validation.

Test Plan:
- `cargo test --all-targets` -- passed, 74 tests
- `cargo clippy --all-targets -- -D warnings` -- passed
- `rumdl check CHANGELOG.md README.md RECONSTRUCTION.md` -- passed
- rendered all six target-rotation states -- visually verified
- `git diff --cached --check` -- passed
This commit is contained in:
2026-08-23 17:53:40 +02:00
parent 4b84460c93
commit 096d923c79
7 changed files with 151 additions and 43 deletions
+11 -6
View File
@@ -15,6 +15,7 @@ pub struct Assets {
pub panel_pair_narrow_b: Texture2D,
pub panel_pair_wide_a: Texture2D,
pub panel_pair_wide_b: Texture2D,
pub panel_target: Texture2D,
pub robot: Texture2D,
pub plunger: Texture2D,
pub ball: Texture2D,
@@ -54,10 +55,11 @@ impl Assets {
];
let wheel_bytes = include_bytes!("../assets/original/images/dat_00600.png");
let wheel = texture(wheel_bytes);
let panel_pair_narrow_a = masked_atlas_pair(wheel_bytes, 0, 45, 45, 90);
let panel_pair_narrow_b = masked_atlas_pair(wheel_bytes, 90, 135, 45, 90);
let panel_pair_wide_a = masked_atlas_pair(wheel_bytes, 271, 362, 91, 90);
let panel_pair_wide_b = masked_atlas_pair(wheel_bytes, 453, 362, 91, 90);
let panel_pair_narrow_a = masked_atlas_pair(wheel_bytes, 0, 90, 45, 90, 45, 90);
let panel_pair_narrow_b = masked_atlas_pair(wheel_bytes, 90, 90, 135, 90, 45, 90);
let panel_pair_wide_a = masked_atlas_pair(wheel_bytes, 271, 90, 362, 90, 91, 90);
let panel_pair_wide_b = masked_atlas_pair(wheel_bytes, 453, 90, 362, 90, 91, 90);
let panel_target = masked_atlas_pair(wheel_bytes, 455, 0, 455, 17, 17, 17);
let robot = texture(include_bytes!("../assets/original/images/dat_00900.png"));
let plunger = texture(include_bytes!("../assets/original/images/dat_00901.png"));
let ball = masked_texture(
@@ -152,6 +154,7 @@ impl Assets {
panel_pair_narrow_b,
panel_pair_wide_a,
panel_pair_wide_b,
panel_target,
robot,
plunger,
ball,
@@ -223,7 +226,9 @@ fn monochrome_texture(bytes: &[u8]) -> Texture2D {
fn masked_atlas_pair(
bytes: &[u8],
image_x: usize,
image_y: usize,
mask_x: usize,
mask_y: usize,
width: usize,
height: usize,
) -> Texture2D {
@@ -237,8 +242,8 @@ fn masked_atlas_pair(
for y in 0..height {
for x in 0..width {
let output_index = (y * width + x) * 4;
let image_index = ((y + 90) * atlas_width + image_x + x) * 4;
let mask_index = ((y + 90) * atlas_width + mask_x + x) * 4;
let image_index = ((y + image_y) * atlas_width + image_x + x) * 4;
let mask_index = ((y + mask_y) * atlas_width + mask_x + x) * 4;
output.bytes[output_index..output_index + 3]
.copy_from_slice(&atlas.bytes[image_index..image_index + 3]);
output.bytes[output_index + 3] = u8::MAX - atlas.bytes[mask_index];