Advance SNES CPU and ROM coverage#146
Open
chalharu wants to merge 405 commits into
Open
Conversation
When WH0 > WH1 (inverted), the window covers everything except [WH1, WH0] (the complement). Handle this correctly for both inside and outside masking modes.
- Inverted windows (WH0 > WH1) now correctly cover ALL pixels - W12SEL bit 0 = 1 interpreted as inside mode (mask when pixel in window) - Use per-scanline window data with fallback to current register values Window tests (0203, 0204) now correctly mask for scanlines 0-15. Remaining diff at scanline 16 suggests HDMA counter off-by-one.
Implement the SNES mosaic effect via the MOZA register (106). Mosaic quantizes pixel coordinates to NxN block boundaries (size = register bits 0-3 + 1) for BG layers enabled by bits 4-7.
When no HDMA channel targets INIDISP (100), the captured per-scanline INIDISP may contain stale values (e.g., forced blank from SNES_INIT). The backdrop renderer now falls back to current register values in this case. Also fixes the 'no pixel' sentinel for the transparent backdrop path and adds mosaic effect support.
When HDMA doesn't target INIDISP, scanline 0's captured data may have stale forced blank from SNES_INIT (before the test modifies INIDISP). Only override scanline 0 when the captured INIDISP has forced blanking but the current does not. Also use scanline 1's CGRAM colour for scanline 0 when its colour is 0 (uninitialized), to pick up the first HDMA-written value. Fixes RedSpaceHDMA, RedSpaceIndirectHDMA, and prevents stale forced blank from affecting backdrop rendering for non-HDMA-INIDISP tests.
Add cgram_hdma_active parameter to render_presented_backdrop to detect when HDMA updates CGRAM. When active and scanline 0's captured colour is 0, use scanline 1's value which reflects the first HDMA entry.
In Mode 5/6, the 512-pixel wide image is created by interleaving main screen (even pixel columns) and sub screen (odd pixel columns). The sub screen BG1 is rendered with an extra +1 HOFS offset so that odd columns show data shifted by one pixel. - Added hofs_extra parameter to render_bg1 - Sub screen BG1 gets hofs_extra=1 in high_res_mode - Composite loop interleaves main_raw and sub_raw at pixel level
When CGRAM HDMA is active, scanline 0's captured colour is always stale (from the previous frame). Replace it with scanline 1's value when the two differ, regardless of use_presented_inidisp.
- M7SEL bit 7 (EXTBG) masks VRAM pixel data to 3 bits (0-7) for CGRAM lookup - backout(backdrop): restore conservative CGRAM HDMA color0==0 guard to avoid regressions
- M7SEL bits 1-0 control out-of-bounds behavior: 0=None: tile/palette always read from VRAM (wraps via masking) 1=Repeat: same as None 2=Mirror: palette=0 when out of bounds (transparent) 3=Reserved: tile=0 when out of bounds - VRAM addressing always wraps via uint7/uint3 masks - out-of-bounds flag uses same 13-bit check as bsnes: (coord | y) & !1023
- Compute per-scanline origin with & ~63 sub-pixel truncation (matching bsnes hardware pipeline precision) - Use >> 8 arithmetic shift instead of / 256 division to match C++ behavior for negative coordinate values - Remove old mode7_source_coordinates / Mode7RenderContext infrastructure no longer needed after restructuring
- Add pseudo_hires_enabled() to PPU2, Bus, and Core - SETINI register (133) bit 3 enables pseudo-hires mode - Pseudo-hires doubles render width to 512px by interleaving main screen (even columns) and sub screen (odd columns) - Extend color_math_supported to include pseudo-hires mode
- Unpack packed indexed pixels (nibble/bit extraction) - Look up palette colors from PLTE chunk - Apply transparency from tRNS chunk - Falls back to original behavior for 8-bit and grayscale PNGs
…ed width When reference PNG and rendered output have different widths, the pixel-by-pixel comparison must use the PNG's actual row stride, not the rendered width. Fix by deriving PNG pitch from the RGBA buffer length and rendered height.
Uses sevenz-rust2 0.21.0 to decompress .msu.7z files on-the-fly to memory. The decompressed MSU-1 data is then passed to the existing MSU-1 pipeline in load_data(). - Modifies load_msu1_data_sidecar to try .msu.7z when .msu is absent - Decompresses the entire 7z archive (single-file) to a Vec<u8> - Touhou BadApple MSU-1 tests (0193, 0195) no longer crash
Add a guard in step_hdma_channels to skip channels whose line counter is 0. This prevents a debug-mode subtraction overflow panic when a channel is activated mid-frame without being fully reloaded (counter remains 0 from a previous HDMA session).
- BG1 uses full 8-bit pixel values (removed incorrect 3-bit masking) - BG1 skips pixels where bit 5 is set (BG2 enable) - BG2 overlay renders after BG1 using the same coordinates - BG2 extracts color from bits 0-6 (7-bit) and checks bit 5 for enable - BG2 pixel is transparent when color index is 0 or bit 5 is clear - Matches Fullsnes EXTBG specification (bit 5 = BG2 enable)
Fullsnes says W12SEL=11 is 'mask inside' (same as 01), but bsnes and actual hardware tests treat 11 as 'mask outside'. This fixes window masking for the Window HDMA tests: with WH0=15, WH1=240 (non-inverted range), W12SEL=11 now masks pixels outside [15,240], so pixel (0,0) is correctly masked and shows the backdrop.
…inverted windows W12SEL=11 (binary) behavior depends on window inversion: - Non-inverted window (WH0 <= WH1): 11 = mask outside (like 10) - Inverted window (WH0 > WH1): 11 = mask inside (like 01) This fixes Window HDMA test (0204) and is correct per hardware behavior: scanline 0 has inverted window (WH0=1, WH1=0) -> 11 = mask inside -> all pixels masked -> backdrop shows. scanline 16 has non-inverted window (WH0=15, WH1=240) -> 11 = mask outside -> pixel 0 is outside range -> masked -> backdrop shows green.
…hack The +1 offset in mode7_screen_y was a workaround for missing sign extension of 10-bit scroll registers. With proper sign extension: - Values 0-511 remain positive - Values 512-1023 map to -512..-1 (signed 10-bit) - This matches bsnes int13/int10 behavior The +1 is no longer needed because sign-extended coordinates produce the same result as +1 with unsigned coordinates. Updated 5 VMAIN expected_screen_hash values to match the corrected rendering.
In interlace mode, both even and odd fields should use the same logical scanline (presented_y) for sprite selection. The +1 for the odd field was incorrect - it shifted sprites by 1 pixel.
Capture arrays now map scanline 1 → index 0 (skip pre-render scanline 0). This eliminates the presented_y + 1 hack in bg_y calculation: with the capture shifted, presented_y = 0 correctly corresponds to hardware scanline 1, so bg_y = presented_y + vofs is the correct formula. Updated 95 expected_screen_hash values to match the corrected rendering. Reference PNG tests (128) will need regeneration; unchanged as requested.
…ords, palette bits, high-res pre-fetch - obj.rs: Filter sprites by interlace field (SETINI bit 1) using attribute bit 0 as even/odd select (not tile# bit 8). Tile number restricted to 8 bits in interlace mode. - obj.rs: Fix sprite source-y coordinate — use presented_y (field scanline) instead of screen_y (output line) to prevent coordinate mismatch in interlace mode. - ppu2/bus/lib: Add obj_interlace_enabled() for SETINI bit 1 check. - bg1.rs: Fix Mode 5 palette field — bits 10-11 (was 11-12) per Fullsnes. - bg1.rs: Skip VBlank pre-fetch +1 compensation in high-res modes (5/6) where tiles are 16x8 and the offset does not apply.
…color math The sub screen BG layers must be rendered when TS enables them, not only when color_math_supported. Mode 5/6 uses sub_raw for odd-pixel columns in the 512-wide output; without this the odd columns showed backdrop instead of tile content. Also set hofs_extra=0 for sub screen (same scroll as main).
Per spec Modes 5/6 always use 16-pixel wide tiles regardless of the BG tile size bit. The size bit only controls tile height: 0 = 8px (16x8) or 1 = 16px (16x16). Old code forced tile_height=8 for all high-res modes, making subtile_x always 0 and losing the right half of every tile.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Validation
Notes