Skip to content

[WIP] Ultrawide#314

Open
enzuru wants to merge 5 commits into
snesrev:masterfrom
enzuru:ultrawide
Open

[WIP] Ultrawide#314
enzuru wants to merge 5 commits into
snesrev:masterfrom
enzuru:ultrawide

Conversation

@enzuru

@enzuru enzuru commented Apr 23, 2026

Copy link
Copy Markdown
image

Hey everyone, I worked with Claude this week to add 32:9 ultrawide support to this project. There are a couple of things remaining:

  • I would like to keep testing further
  • I would like to spend more time understanding Claude's changes, which I believe is my responsibility as a contributor
  • There are some useless files in here like shell.nix and I need to reset the ini file as well

Description

This adds 32:9 support.

Will this Pull Request break anything?

It shouldn't!

Suggested Testing Steps

Test on an ultrawide monitor.

Claude's description of its own changes

Here's a summary of all changes since the fbbb3f9 (Add BPS support) base:

32:9 Ultra-Widescreen Support

These changes add support for 32:9 ultra-widescreen (796px viewport, 270px extra per side) to the zelda3 ALTTP reimplementation.

Build / Config
  • shell.nix — Nix shell with SDL2, libGL, python3+pillow+pyyaml. Forces -std=gnu17 because GCC 15 defaults to C23 which breaks old-style empty function parameter lists.
  • zelda3.ini — Set to 32:9, fullscreen, autosave enabled.
  • .gitignore — Ignore .agent-shell/ directory.
Bug Fixes
  • src/config.hextended_aspect_ratio changed from uint8 to uint16. The value 270 (for 32:9) overflowed uint8 max 255, silently wrapping to 14.
  • src/config.c — Added 32:9 as a recognized aspect ratio string.
  • src/types.hkPpuExtraLeftRight increased from 96 to 320 to size PPU pixel buffers large enough for 32:9.
  • snes/ppu.hextraLeftCur, extraRightCur, extraLeftRight widened from uint8_t to uint16_t (values > 255 needed).
Extended Tilemap (core feature)

The SNES tilemap is 64 tiles wide (512px) with a ring buffer. To exceed this limit:

  • snes/ppu.h — Added extTilemap[0x1000] (4 pages, 0x400 words each) and extTilemapEnabled flag to the Ppu struct. These hold tile data for columns beyond the 64-column VRAM tilemap.

  • snes/ppu.c — PpuDrawBackground_4bpp (old renderer):

    • tps[] expanded from 2 to 4 page pointers. Pages 0-1 point to VRAM (ring buffer data), pages 2-3 point to extTilemap when enabled.
    • NEXT_TP() macro cycles through all 4 pages: 0→1→2→3→0.
    • Starting page forced to (x >> 8) & 1 — always starts in VRAM, never in extTilemap.
    • Added #undef NEXT_TP before the 2bpp renderer to avoid redefinition warning.
  • snes/ppu.c — ppu_getPixelForBgLayer (new renderer):

    • Computes distance from viewport left edge. If dist >= 512, reads from extTilemap; otherwise uses the original VRAM path.
  • snes/ppu.c — PpuSetExtraSideSpace:

    • Bypasses the tilemap_extra clamp entirely when extTilemapEnabled is true, allowing the full 270px per side.
  • src/overworld.c — Overworld_FillExtTilemap() (new function):

    • Called every frame during overworld mode (module 9).
    • Walks tile columns exactly as the renderer does, tracking the current page and position to write each tile to the correct destination (VRAM or extTilemap).
    • Uses two coordinate systems: PPU register scroll (10-bit wrapped) for tilemap addresses matching the renderer, and full game scroll (BG1HOFS_copy2/BG2HOFS_copy2) for map data lookup in dung_bg1/dung_bg2.
    • Processes both BG1 and BG2 layers.
    • Overwrites stale ring buffer VRAM data and fills extTilemap for overflow columns.
  • src/overworld.h — Declares Overworld_FillExtTilemap(struct Ppu *ppu).

  • src/zelda_rtl.c — ZeldaDrawPpuFrame:

    • Sets extTilemapEnabled = true BEFORE ConfigurePpuSideSpace() so the clamp bypass takes effect.
    • Calls Overworld_FillExtTilemap() after ConfigurePpuSideSpace().
Key bugs found and fixed during development
  1. uint8 overflow for aspect ratio value 270
  2. VRAM fixup using absolute scroll coords for dung_bg2 (which uses local area coords)
  3. Renderer starting page using & 3 instead of & 1 — broke rendering when hScroll >= 256
  4. PPU scroll registers are 10-bit (0-1023) but overworld uses full coordinates (1024+) — had to use BG2HOFS_copy2 for map data lookup
  5. ExtTilemap row addressing used game vScroll instead of PPU register vScroll, causing misalignment

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.

1 participant