Skip to content

Releases: SgtBilko76/snes9x-3D

Snes9x VR 0.1 — first beta

Pre-release

Choose a tag to compare

@SgtBilko76 SgtBilko76 released this 20 Sep 13:57

Meta Quest port by Sgt. Bilko.

A port of Snes9x to the Meta Quest that puts the SNES on a curved screen and
reconstructs depth from what the console was already telling the renderer.

The screen

  • Curved screen as an OpenXR cylinder layer, composited by the runtime at full
    resolution rather than resampled onto geometry, over a dim backdrop.
  • Rendered at 2048x1536 per eye, about twice what the headset resolves across
    the default screen size, so the compositor's downsample does the
    antialiasing.
  • Smoothing: Pixels, Sharp (default) or Soft.
  • Screen distance, width and position adjustable, and remembered.

Depth

The SNES has no 3D to read back, so depth is reconstructed three ways, in
increasing order of how real it is:

  • Layer order. The core writes a priority value per pixel as it composites,
    which gives the layer ordering for free. Those values are an ordering rather
    than a distance, so the layers a scene actually uses are ranked and spread
    evenly.
  • Split layers. Each background and the sprites render into buffers of
    their own as well as the composite, so a displaced layer uncovers the one
    behind it instead of smearing. At zero separation the result is the core's
    own composite, pixel for pixel.
  • Mode 7. A Mode 7 ground plane changes its matrix every scanline, and that
    matrix says how far away each row is. So a road recedes properly instead of
    hanging flat, and sprites standing on it take the distance of the ground
    under their feet.

Stereo strength is a distance in millimetres, capped at half an
interpupillary distance, because past one IPD the eyes would have to diverge.

Frame pacing

The display rate is matched to the cartridge rather than the other way round:
120 Hz for a 60 fps NTSC game, which is exactly two display frames each. PAL
gets 90 Hz, the closest the headset offers to a multiple of 50.

Everything else

  • Reads .sfc, .smc, .fig, .swc and .zip.
  • In-headset ROM browser, and a folder browser for choosing where ROMs live.
  • Ten save-state slots per ROM, plus battery saves.
  • Touch controllers, and Bluetooth gamepads alongside them.

Fixed since the first build of this beta

  • Super FX games no longer show a black screen. Settings is zeroed before
    the defaults are applied, and SuperFXClockMultiplier is a percentage the
    chip's cycle budget is scaled by, so at zero Star Fox ran perfectly while
    being handed no cycles to draw with. The same omission left OneClockCycle,
    OneSlowClockCycle and TwoClockCycles at zero, which is every CPU timing
    decision the core makes, and the sound interpolation at none.
  • Controls are remappable from a Controls... page in the menu. Each
    physical input carries whichever SNES button you put on it; the defaults are
    unchanged.
  • Two more smoothing levels between Sharp and Soft.
  • No ROM is loaded on startup; the app opens on the ROM list.
  • The screen sits closer by default, 3 m rather than 4. The apparent size
    comes from the width angle, so this changes where it is without changing how
    big it looks.

Pico

One package now covers Pico headsets as well, with their manifest entries and
controller profile alongside Meta's. Untested: there was no Pico to try it
on.
See the Pico section of the README for what is most likely to need
fixing and how to tell from logcat.

Known limits

  • PAL games still judder slightly: no rate the headset offers divides 50.
  • Sprites take the depth of the ground beneath them, so an airborne object is
    placed as though it had landed. The DSP-1 projections that would fix this are
    captured but not yet associated with sprites.
  • Super FX games (Star Fox) get layer-order depth only. There is no transform
    stage to hook: the geometry lives in ROM code as ordinary integer
    arithmetic. They also boot to a black screen for a good fifteen seconds
    before the first picture, which is the game, not the port.
  • A ROM folder outside the app's own directory needs all-files access, granted
    once from the menu.

Install

adb install Snes9xVR-0.1.apk

Sideloaded, so it appears under the headset's unknown-sources list. Nothing
is loaded on startup: the app opens on the ROM list. Put ROMs in
/sdcard/Android/data/com.snes9x.vr/files/roms, or point Settings → ROM
folder
anywhere else and grant storage access from the same page.

Built and tested on a Meta Quest 3. Pico support is in the same APK but has
never been run on the hardware -- see the README if it does not start.

sha256: aa5c8fbfd302b156be780a52cfa9b829a42d304c2ae49ec5f5cecaa92d60ae14