Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .github/workflows/world-override-orientation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: world override orientation
on:
pull_request:
workflow_dispatch:
permissions:
contents: read
jobs:
compositor:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v7
- run: sudo apt-get update && sudo apt-get install -y luajit love xvfb
- run: luajit tests/engine/world_override_orientation.lua
- run: luajit tests/engine/legacy_shader_compat.lua
- run: xvfb-run -a love tools/legacy-shader-check
env:
LIBGL_ALWAYS_SOFTWARE: "1"
88 changes: 88 additions & 0 deletions LICENSE-ROXAS2712.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Roxas2712 — Fork Contributions

Version 1.0 · Effective 25 October 2026

Copyright © 2026 Roxas2712, to the extent of rights held.
All rights reserved except as expressly granted below or already granted.

## 1. Scope and ownership

This notice applies only to original contributions made by Roxas2712
(GitHub: Roxas2712) to `Roxas2712/Gen2Recomped`, including original additions
within modified files, insofar as he owns the relevant rights. Git history,
pull-request diffs and source provenance identify contributions; a commit
author or a whole-file change alone does not establish ownership of every
part of that file.

It does not claim ownership of Cedric's work, Gen1Recomp / BOIS CLUB GAMES
work, other contributors' work, third-party dependencies, or ROM-derived
content. Their applicable licences and notices remain in force. It does not
grant permission to distribute the complete combined fork where another
rights holder's permission is required.

## 2. General permission and reserved rights

For contributions covered by this notice and not already licensed more
broadly, you may read and study the published source and make private,
non-commercial modifications and builds for your own use. This grants no
general permission to redistribute, sublicense, sell, or offer those
contributions as a hosted service. Other uses require Roxas2712's
written permission, except for the specific permission below and rights
available independently under applicable law.

Keep the relevant copyright, licence and attribution notices. Do not
represent Roxas2712's contributions as exclusively authored by someone
else. Public source availability alone does not put them in the public
domain or grant an open-source licence.

## 3. Specific permission for Cedric / UNDERdecoded

Roxas2712 expressly grants Cedric (Ced; GitHub: UNDERdecoded /
UNDERdecodedHD) a non-exclusive, worldwide, perpetual, royalty-free
permission to use, reproduce, integrate, modify and distribute the covered
contributions that Roxas2712 submits or expressly offers through pull
requests to `UNDERdecoded/Gen2Recomped`, for Cedric's Gen2Recomped /
RetroRecompiled project. This includes its renamed continuation maintained
by Cedric, its official builds, and its commercial operation.

Cedric may license the incorporated contributions to recipients as part of
that project, subject to preserving this permission's applicable credit and
notice requirements. This permission is not a copyright assignment, is not
exclusive, and does not cover unpublished work, separate repositories,
ModCompass service operation, credentials, or content not offered in those
pull requests. Roxas2712 retains his own rights to his contributions.

For uses relying on this permission:

- retain the relevant source copyright and licence notices;
- give visible credit in the project's README or equivalent public project
page, and in the application's existing About / Credits view, if present;
- use at least the following credit, or a substantially equivalent one:

> Contributions by Roxas2712 —
> https://github.com/Roxas2712

A maintained consolidated contributor credit is sufficient; a separate
credit on every screen or for every change is not required. Adapted
contributions must not be attributed exclusively to another author. Other
contributors' credits must also remain intact.

## 4. Earlier licences and permissions remain effective

This notice does not revoke, narrow, or retrospectively add conditions to
any permission already validly granted, including MIT / GPL grants,
separate agreements, or permissions arising from previously submitted
pull requests. Where an earlier grant permits a use independently of this
notice, its existing terms govern that use. For such earlier uses, the
visible credit above is requested to the extent it is not already required.

For subsequent contributions, this is the default statement of Roxas2712's own reserved rights and the specific PR permission, subject to any
applicable existing licence obligations or separately agreed terms. It
does not change another rights holder's licence or guarantee compatibility
of a particular combination of code.

## 5. No warranty

To the extent permitted by applicable law, these contributions are provided
as is, without warranty. No support obligation, endorsement, or rights to
third-party code, game assets, names, or trademarks are granted.
54 changes: 54 additions & 0 deletions docs/qa/shader-compiler-options.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Shader compiler options and canvas orientation

Explicit native-coordinate shaders must not be normalized a second time. The
compatibility compiler now recognizes `POKEPORT_NATIVE_CLIP_SPACE` and
`POKEPORT_LEGACY_CLIP_SPACE_ADAPTED` in the compiler's `defines` option, as well
as in source. Both named definitions and the array form preserve their original
arguments, including filenames, FileData, and the options table. Definition
presence counts even with a value of zero or false, matching the preprocessor.

This path avoids an additional file read, comment scan and source allocation;
no frame-rate improvement is claimed. A preprocessor guard also preserves
definitions supplied by inherited compiler options without inspecting option
metatables in the Lua wrapper. Identifiers with an `_EXTRA` suffix are distinct
and do not disable legacy normalization.

## Reproduction

Run `tests/engine/legacy_shader_compat.lua` with the engine test runner. For GPU
verification, set `SHADER_OPTIONS_ENGINE` to this checkout, an unused isolated
`POKEPORT_IDENTITY=oasc-gen2recomp-qa-shader-options-<unique>` and
`POKEPORT_GRAPHICS_BACKEND` to `opengl` or `metal`, then launch
`tools/shader-options-check` with LÖVE 12. Optional `SHADER_OPTIONS_OUT` saves
the native and independent reference portrait images. Run GPU backends serially.

The checker compares the wrapped compiler with the runtime's unwrapped
constructor, checks an independently upright reference, and verifies that
invalid shader sources still fail. It exercises combined/split source,
filenames/FileData, map/array/inherited definitions, direct/table render targets,
four sizes including portrait, and DPI scales 1 and 2. Native and already-adapted
definitions remain unchanged; ordinary matrix-based 2D and default legacy
coordinates retain their previous orientation.

## Source-bound results

- Production module SHA-256:
`c99b3c9b9ab8be4801ba894cb2bfb7cc0d2deb88cb8de24adff8554bed863dca`.
- GPU checker SHA-256:
`29539a3d522a8369347369b2fd312309d1743755200337800e6990ed9c065fba`.
- LÖVE 12 build `937eb3b`, macOS: OpenGL and Metal each pass **510 checks and
240 exact full-RGBA image pairs** on those bytes.
- Existing legacy orientation GPU checker: **304 checks / seven cases** on each
backend, including embedded HUDs, culling, matrices and state restoration.
- Independent upstream patch: **119/119** targeted CPU checks. Composed fork:
**324/324** engine suites, **3/3** SDK suites, and B30 profile pass.
- Before correction, the new GPU checker fails because a shader explicitly
marked native in compiler options is rewritten. Previous production module
SHA-256: `b23fd6d20f136f54f78793839151a5f8d0abd76793da7eb541fc5802a47d00ca`.

A fresh unchanged supplied Johto package also failed before camera verification
with a dynamically generated function exceeding LuaJIT's 60-upvalue limit. The
same package inventory fails identically on the parent composed fork without
this correction. Both failures are retained; neither is gameplay acceptance.
Windows GPU execution and full mod compatibility remain unverified. No ROMs,
mod sources/assets, imported caches or player profiles are included.
50 changes: 50 additions & 0 deletions docs/world-override-orientation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Legacy world and embedded HUD orientation on LÖVE 12

LÖVE 12 normalizes canvas clip coordinates differently from LÖVE 11. Legacy
custom 3D shaders already invert clip-space Y themselves. Reflecting the
completed world image corrected those 3D pixels but inverted ordinary 2D
menus, battle HUDs and effects drawn into that same image.

`src/render/LegacyShaderCompat.lua` now restores the LÖVE 11 high-level shader
coordinate contract at shader creation, before those draws are combined. It
adapts the `position` entry point, its projection argument and the global
projection matrix consistently. The canvas uniform follows shader/canvas
changes and graphics-state restores. Ordinary matrix-based 2D shaders cancel
the paired reflections and retain their normal orientation. LÖVE 11, raw
`vertexmain` entry points and shaders declaring
`#define POKEPORT_NATIVE_CLIP_SPACE 1` are unchanged.

The compositor no longer mirrors ordinary world overrides. An explicitly
unconverted image may still request `worldOrientation = "legacy"`; `native`
and detached `renderData.v1` retain their native convention. The existing
field-effect counter-transform follows only that explicit mirror policy.
The shader compatibility layer handles the usual mixed 3D/2D image before
presentation, so its HUD can remain upright without transforming the HUD.

## Scoped evidence

- The real shader creation/state adapter passes 57 ROM-free checks and the
compositor/field-effect policy passes 151, both independently and on the
composed fork.
- The standalone GPU fixture passes 304 checks in seven cases on LÖVE 12
OpenGL and Metal, and 220 on stock LÖVE 11.5. It covers actual custom and
matrix-based vertex paths, canvas/window targets, state restoration and
mixed artwork. The negative control disables the shader correction and
fails the asymmetric pixel assertion.
- Actual Red/VASC battle/menu work and native Emerald/FireRed OpenGL
regressions were tested at their recorded earlier source checkpoints.
These are distinct from a new complete Windows or all-games acceptance.
- The current Crystal checkpoint uses the unmodified supplied Johto package
on both backends: actual First/Third V/F6 input, native grid movement and
upright StartMenu, plus the Mart/Center geometry and menu probes. See the
[Johto report](https://github.com/Roxas2712/Gen2Recomped/blob/f56a81f6e0eb97ab5024706fca3f07cfe4d1eca0/docs/johto-native-compatibility.md) for exact sources, normal
no-mod staircase/house exits and the remaining renderer/interior gaps.

The earlier whole-image-mirror evidence in
`docs/validation/love12-world-orientation.json` is historical; it does not
establish that an embedded battle HUD was correct. The repeatable current
fixtures are `tests/engine/legacy_shader_compat.lua`,
`tests/engine/world_override_orientation.lua`,
`tools/legacy-shader-check/main.lua` and
`tools/world_orientation_gpu_driver.lua`. Windows hardware, every mod feature,
all maps/doors and complete engine parity remain open.
1 change: 1 addition & 0 deletions main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,7 @@ end
function love.load(args)
BootTrace.mark("love.load enter")
GraphicsStack.install()
require("src.render.LegacyShaderCompat").install()
pcall(function() require('src.core.SwitchAudioCheck').run() end)

-- Teach SDL about the pads its built-in database misses (Switch Pro over
Expand Down
2 changes: 2 additions & 0 deletions src/mods/Schemas.lua
Original file line number Diff line number Diff line change
Expand Up @@ -894,6 +894,8 @@ R.render_pipelines = {
-- you hand back to the window, so a supersampled or low-res canvas is
-- fine too -- but matching the pixel size is the one that is exact.
drawWorld = f.opt(f.fn),
-- Image convention for legacy LÖVE 11 custom 3D shaders on LÖVE 12.
worldOrientation = f.opt(f.enum { "legacy", "native" }),
-- (canvas, ctx) -> canvas: post-process the WORLD image, before the UI
-- composites over it -- a depth-of-field or colour grade that must not
-- touch the dialog boxes and menus sitting on top. Only runs when some
Expand Down
2 changes: 1 addition & 1 deletion src/render/ClipSpaceCompat.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ function C.shader(source)
local count
source,count=source:gsub("vec4%s+position%s*%(","vec4 legacyPosition(")
if count==0 then return source end
return source..[[
return "#define POKEPORT_NATIVE_CLIP_SPACE 1\n"..source..[[
#ifdef VERTEX
vec4 position(mat4 transform_projection, vec4 vertex_position) {
vec4 clip=legacyPosition(transform_projection,vertex_position);
Expand Down
Loading