Skip to content

rex3: CIDMATCH is a mask of permitted CIDs, not an equality value - #105

Merged
techomancer merged 1 commit into
techomancer:mainfrom
iblowmymind:rex3-cidmatch-mask
Sep 14, 2026
Merged

techomancer merged 1 commit into
techomancer:mainfrom
iblowmymind:rex3-cidmatch-mask

Conversation

@iblowmymind

@iblowmymind iblowmymind commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

Problem

REX3 CLIPMODE bits 12:9 (CIDMATCH) are a four-bit permission mask: bit N permits a framebuffer write to a destination pixel whose two-bit CID is N (0000 rejects every write, 1111 permits all). See docs/rex3.pdf, table 16 and section 3.3.

Both the interpreter and the REX JIT treated the field as an equality value and compared it against AUX's low nibble, which also includes the popup bits. That rejected legitimate writes. It showed up as drawing artifacts in StudioPaint: the captured CLIPMODE was 0x00000403 (mask 0010, i.e. CID 1), and the destination AUX byte was 0x11 (CID 1), yet the write was dropped.

Disabling the REX JIT did not help, because the interpreter had the same bug. Its screen-to-screen copy path also skipped the destination CID check entirely.

Change

  • src/rex3.rs: a cid_allows_write helper implements the mask check. Pixel draws and screen-to-screen copies both use it; the copy path checks the destination.
  • src/rex3_jit/compiler.rs: the emitted check for block draws and integer lines now tests (mask >> cid) & 1, using only AUX bits 1:0.
  • Framebuffer reads remain unchecked, as before.

Tests

  • New: cid_write_masks_interpreter and cid_write_masks_jit cover every mask × CID × popup value for block draws, integer lines and screen-to-screen copies. The JIT variant checks jit_go_count, so an interpreter fallback can't make it pass.
  • Existing tests: rex3init now uses mask 1111 rather than 0000 (under the correct semantics, 0000 rejects everything), and explicit JIT compile requests use that CLIPMODE key.
cargo test --release --features rex-jit --lib -- rex3

Docs: docs/rex3.md CIDMATCH description corrected; new note rules/rex3/cidmatch-is-a-mask.md.

CLIPMODE bits 12:9 are a four-bit permission mask: bit N permits a
framebuffer write to a destination whose two-bit CID is N. Both the
interpreter and the REX JIT compared AUX's low nibble (CID + popup bits)
for equality against the field, which rejected legitimate writes — seen as
drawing artifacts in StudioPaint (CLIPMODE 0x00000403, destination AUX 0x11).
Disabling the REX JIT did not help because the interpreter had the same
bug, and its screen-to-screen path skipped destination CID checking
entirely.

Tests cover all masks, CIDs and popup values for blocks, integer lines and
copies on both paths; the JIT variant checks the dispatch counter so an
interpreter fallback can't pass it. Test init now uses mask 15, and explicit
compile requests use that CLIPMODE key.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019t4zZR7XH1DeuPZbVooWNS
@techomancer
techomancer merged commit 4c6e37e into techomancer:main Sep 14, 2026
1 check passed
@iblowmymind
iblowmymind deleted the rex3-cidmatch-mask branch September 14, 2026 14:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants