Enhancements

None of this was on the hardware. Where an option is off, output is bit-identical to stock. Full list: libretro docs.

True colour shipped v3.2.0

The blitter computes Gouraud shading with 16 fraction bits, then throws them away in the 16-bit CRY write. virtualjaguar_true_color keeps them, in a shadow framebuffer. Game-visible RAM stays bit-identical.

Stock 16-bit CRY, off
Cybermorph terrain, stock 16-bit CRY rendering: visible banding on shaded polygon surfaces
Cybermorph, frame 850. 304 unique colours.
True colour, on
Cybermorph terrain, true-color rendering: smooth gradients on shaded polygon surfaces
Same frame, same inputs. 450 unique colours.
Cybermorph off / on / difference
Three-panel comparison: stock frame, true-color frame, and a difference map amplified 64 times showing shading refinement across polygon surfaces
Difference amplified 64x. 45.9% of pixels refined, and every changed channel moves exactly one quantization step.
304 -> 450 unique colours, peak 423 -> 702. Both blitter engines agree exactly. With the option off, 600 frames hash bit-identical to develop. CRY 16bpp only, roughly 8 MB when enabled. Shipped in v3.2.0, PR #341.

Internal resolution 2x complete v3.3.0

The blitter is the Jaguar's rasterizer, and it walks source textures with 16.16 fixed-point steps, then rounds each output pixel to the nearest texel and throws the rest away. virtualjaguar_internal_resolution (1x default, 2x, restart required) re-samples those same walks at double density into a shadow surface. The extra pixels are source data the hardware sampled past. No interpolation or filtering is involved.

As of v3.3.0 the pipeline is complete. Supersampling covers fractional-walk blits (Stage 2), the Object Processor's scaled sprites (Stage 3, SCBITOBJ) including 8bpp CLUT objects, and both CRY and RGB16 direct video modes render the recovered detail to the screen.

The RGB16 renderer mattered more than it sounds. Measured across about 3,000,000 scaled calls, Val d’Isère and Primal Rage are 100% RGB16: before v3.3.0 an entire class of titles produced supersampled content and then threw it away at scanline time. The CLUT extension is what reaches 2D games at all. Scaled CLUT objects are 81% of the truly-scaled pixels in International Sensible Soccer and 76% in Val d’Isère.

The emulated machine never sees any of it. The stock framebuffer stays bit-identical and savestate digests match between 1x and 2x. Both are proven per-title by committed tooling, hires_box_check and hires_state_digest, rather than asserted.

Alien vs Predator, frame 6000 1x / 2x
Alien vs Predator frame 6000, two panels side by side: left is the 1x frame with every pixel doubled, right is the same frame at 2x internal resolution. Both show an Alien's claw in a textured corridor facing a chevron-panelled door; the panels differ only in fine texture detail.
Same ROM, same input script. Only the option differs. At 1:1 the difference is subtle. This buys fine texture detail, not a change in composition or colour.
Corridor wall magnified 6x
Magnified 6x crop of the corridor wall and floor. In the 1x panel the wall ribs are flat 2x2 blocks of a single colour; in the 2x panel the same ribs carry intermediate texel values and the diagonal wall-floor edge steps in half-pixel increments.
Same frame, magnified 6x from the 1x pixel grid. The ribbed wall is where it reads: those columns are minified source walks, so the extra scanline lands on a different texel about half the time.
Chevron door magnified 6x
Magnified 6x crop of the chevron-panelled door. The 2x panel resolves sub-texel shading along the chevron edges and across the panel face that the box-replicated 1x panel cannot represent.
Some of what appears here is an intermediate value between two adjacent texels, a finer gradient reading as stippling at this magnification, rather than new structure. It is still recovered source data. It is not extra geometry.
Val d’Isère, 46 MPH 1x / 2x
Val d'Isere Skiing and Snowboarding, downhill run: left is the 1x frame pixel-doubled, right is the same frame at 2x internal resolution. The snowboarder, trees and course furniture carry finer edges on the right.
Same ROM, same input script. Only the option differs. This title measured a flat 0.0000% before v3.3.0: every scaled object on screen is an 8bpp CLUT sprite, and its video mode is RGB16. Both v3.3.0 additions are load-bearing here.
Course ahead magnified 3x
Magnified 3x crop of the course ahead of the snowboarder. The tree clusters in the 2x panel resolve branch-level structure where the 1x panel shows flat 2x2 blocks.
The densest-detail window, located by measurement rather than by eye. The trees are scaled 8bpp CLUT objects, exactly the path Stage 3's CLUT extension supersamples, and at 2x they resolve branch structure the 1x walk stepped past.
Same crop 1x / 2x / difference 8x
Three panels: the 1x crop, the 2x crop, and their difference amplified 8 times. The difference concentrates on the tree clusters.
The recovered detail concentrates exactly where the scaled objects are. The flat snow, which carries no sub-texel information, stays black.

Doom and JagDoomEX

Doom is CRY-mode and blit-rendered, so it exercises the Stage 2 path. So does the JagDoomEX romhack: the per-title database recognizes it by its patched CRCs and enhances it identically. The frame below is from the attract demo, machine-selected for the highest measured sub-pixel density in the run, 13.9% of 2x2 blocks.

JagDoomEX, demo frame 1800 1x / 2x
JagDoomEX demo frame: left is the 1x frame pixel-doubled, right the same frame at 2x internal resolution with true color.
Same ROM, same (empty) input. Only the options differ: 2x plus true colour, both set by hand for this capture. The per-title database applies 2x alone to Doom and the JagDoomEX CRCs; true colour was dropped from those rows once a pixel diff measured it at 0.0000%.
Wall crop 1x / 2x / difference 8x
Three panels of a wall crop magnified 3x: 1x, 2x, and the difference amplified 8 times showing dense horizontal runs of recovered texels across the wall texture.
Magnified 3x. 14.7% of the frame's pixels change, and the diagonal mortar seam resolves continuously at 2x where the 1x walk renders it broken. Doom's palette is deliberately murky, so the honest presentation is the difference map. At 1:1 this reads as texture solidity, not as a different picture.

Which titles benefit, measured

The number is the share of 2x2 output blocks carrying genuine sub-pixel detail. It is a coverage figure, not “N% better image”. Every scene below was screenshot-verified in real gameplay, and is identical on both blitter engines.

TitleSceneBlocks with real sub-pixel detail
Alien vs Predatortextured corridor, standing still30.6%
Alien vs Predatorsame level, walking into a door13.0%
Skyhammerin-mission cockpit, city flight3.4-17.7%
DoomE1M1 gameplay8.7%
Missile Command 3DOriginal 3D gameplay5.0-5.9%
Val d’Isère Skiingdownhill run (new in v3.3.0: RGB16 + scaled CLUT)2.5-7.2% (was 0.0000%)
International Sensible Soccermatch kickoff (scaled CLUT sprites)0.1-0.6% (was 0.0000% outside 16bpp scenes)

The AvP spread is the honest shape of this feature. A corridor viewed down its length is minification-heavy and recovers a lot. A wall pressed against the camera is magnification-heavy and recovers little. Stage 2 recovers information only where the source walk minifies.

Which titles it does nothing for

Three census candidates measured a true 0.0000%, for three different reasons.

  • Towers II: zero non-uniform blocks across 1.17 billion rendered pixels. Its content is information-theoretically flat for this feature.
  • I-War and Towers II: they magnify their textures. 81% of I-War's qualifying walks consume less than one texel per pixel, so the half-step sample lands inside the same texel and there is nothing to recover. Information-theoretic, not a bug.
  • Cybermorph and Checkered Flag: effectively none of their blits use a fractional source walk, 13 and 8 qualifying blits out of roughly 1.7 M each, and Cybermorph re-measured 0.0000% on v3.3.0 even with true colour on. There is nothing for this feature to hook into. Use True Color there instead, which is why the per-title defaults ship it for Cybermorph.

Iron Soldier 2 on CD is unverified, not zero: its gameplay could not be reached headlessly. This helps some games. It does not help all of them.

The cost

2x scales with screen area, so budget for it on a handheld. Stage 1 measured Doom at +13% frame time, and Stage 2 adds roughly +1.5% (Doom) to +7.4% (Missile Command 3D) on top of that. At 1x the cost is nil and the output is bit-identical.

Stage 1 and 2 shipped in v3.2.0 (PR #353, PR #359). Stage 3 and the RGB16 renderer shipped in v3.3.0 (PR #381, PR #383, the CLUT extension in #367). Method, per-title input scripts and instrumentation: docs/avp-renderer-analysis.md · corpus census · design · epic #338.

HD texture dump and replacement shipped v3.4.0

Both halves of a texture-pack pipeline. virtualjaguar_texture_dump writes every unique blit source the game uses to <system>/vj_texdump/<CRC32>/ as a PNG named by a stable content hash: FNV-1a 64 over format, dimensions and raw source bytes.

The palette is deliberately excluded from that hash. The Jaguar blitter never sees one, and a key the replacement pipeline cannot discriminate would strand every pack drawn against it. The identity contract is frozen in docs/texture-dump.md.

Redraw a tile, keep its filename, move it one directory over to vj_texpacks/<CRC32>/, and it presents in place of the original. Packs are true colour. Nothing quantises back to CRY, and a pack pixel with alpha below 128 keeps the stock pixel. Replacement rides the true-colour shadow framebuffer and never writes the emulated machine, so savestates, rewind, run-ahead and netplay stay bit-identical with or without a pack. A pack cannot desync a link game.

Tier 1 covers 16bpp source tiles at 1x through straight-copy blits, the sprite and UI class the dump mode was built around. Indexed sources (tier 2) and Stage 2 hi-res surfaces (tier 3) are designed but not implemented; those entries are skipped and the stock pixel presents. The replacement option only appears when a pack directory exists for the loaded cartridge.

Shipped in v3.4.0 · #369 · identity contract: docs/texture-dump.md.

Clock scaling

virtualjaguar_m68k_clock_scale runs 0.5x to 3x, and virtualjaguar_risc_clock_scale 0.5x to 2x. Bus latencies stay in wall time at any scale, so pacing and pitch do not drift. CI proves it at non-1x scales.

v3.1.0 notes (#314, #316) · cycle-domain contract #318, PR #337 (merged).

CD read speed

virtualjaguar_cd_read_speed runs from 1x (hardware-faithful) to instant, on the HLE path. Streaming reads keep fast transfers from stomping in-flight game code. Regression-tested.

Crash watchdog

virtualjaguar_crash_detect, default on, matches known failure signatures each frame. Your frontend log names the subsystem that broke.

src/core/crash_detect.c. Signatures and thresholds are in the header comment.

Per-title defaults shipped v3.2.0 and later

virtualjaguar_pertitle_defaults, default on, applies known-safe presets for recognized games: 2x for Doom and Alien vs Predator, true colour for Cybermorph, 2x plus true colour for I-War and Skyhammer, and more as titles are verified. A preset only touches options you have left at their defaults. Any option you set yourself always wins. Disable it for stock behaviour on every title.

Title table: src/core/titledb.c, where every row carries its evidence citation · #368.

Blit memoization shipped v3.3.0

Some titles re-render a bit-identical scene every engine cycle while the player is idle. virtualjaguar_blit_memo skips a blit only when its entire input state provably matches an earlier identical blit, and then replays the recorded writes. Output is bit-identical by construction, and a verify mode executes every would-be skip and checks it.

Enabled per title via the enhancement database, which currently carries no rows for it: the mechanism ships ahead of the data, so nothing turns it on by default. 2,546,482 corpus verifications, zero divergences.