Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
644aa83
Add version-aware capability queries to the mod API
Roxas2712 Oct 21, 2026
044ff92
Add opt-in unified mod content records across generations
Roxas2712 Oct 21, 2026
4822a59
Add opt-in unified hook and event record boundaries
Roxas2712 Oct 21, 2026
886fca5
Add detached read-only world and party queries
Roxas2712 Oct 21, 2026
9b7bc09
Add guarded public world actions and native flight
Roxas2712 Oct 21, 2026
5934814
Allow capability tests to follow additive native flight support
Roxas2712 Oct 21, 2026
52b0055
Add detached read-only battle snapshots for mods
Roxas2712 Oct 21, 2026
9044909
Add revision-bound public battle actions through native commands
Roxas2712 Oct 21, 2026
418b55f
Add revision-bound public party, bag and dialogue UI actions
Roxas2712 Oct 21, 2026
4bfa668
Add opt-in prevalidated portable world dialogue scripts
Roxas2712 Oct 22, 2026
b46e128
Add read-only map overview and encounter table queries
Roxas2712 Oct 22, 2026
40e8980
Integrate public API prerequisites (#90–#97)
Roxas2712 Oct 22, 2026
61edab0
Integrate portable script prerequisite (#98)
Roxas2712 Oct 22, 2026
4008ae2
Integrate world-overview prerequisite (#99)
Roxas2712 Oct 22, 2026
69c3474
Add shared API 3 entry and pinned cross-engine contracts
Roxas2712 Oct 22, 2026
ab7d941
Add validated API 3 world warps and cross-engine contracts
Roxas2712 Oct 22, 2026
2ea78e3
Add API 3 object visibility and block edits with shared contracts
Roxas2712 Oct 22, 2026
f184256
Add API 3 public NPC actions with cross-engine contracts
Roxas2712 Oct 22, 2026
602302a
Add guarded API 3 wild encounters and shared contracts
Roxas2712 Oct 22, 2026
b191fdc
Add guarded API 3 native map invalidation
Roxas2712 Oct 22, 2026
569b789
Map API 3 native flags to version-correct VM storage
Roxas2712 Oct 22, 2026
20fd4f6
Add prevalidated portable flag script commands
Roxas2712 Oct 22, 2026
235b8f9
Add portable wallet, inventory and party script actions
Roxas2712 Oct 22, 2026
7671788
Add portable native gift scripts with owned UI continuations
Roxas2712 Oct 22, 2026
25af724
Add validated portable object and block script commands
Roxas2712 Oct 22, 2026
4632d3a
Add owned portable movement and facing scripts
Roxas2712 Oct 22, 2026
7e62026
Add portable native travel with destination-aware preflight
Roxas2712 Oct 22, 2026
7f46d4d
Add portable wild and static battle scripts
Roxas2712 Oct 22, 2026
089a4c9
Add native portable trainer battle scripts
Roxas2712 Oct 22, 2026
1a09b6c
Add portable native marts with owned transaction callbacks
Roxas2712 Oct 22, 2026
1fa9d59
Add validated portable sound and music script commands
Roxas2712 Oct 22, 2026
8a6eca8
Add owned deferred dialogue audio for portable scripts
Roxas2712 Oct 22, 2026
5528ea2
Add bounded portable save-field and option commands
Roxas2712 Oct 22, 2026
1d9b8ef
Map portable move effects to native Gen1-3 handlers
Roxas2712 Oct 22, 2026
72f4fb2
Add validated read-only version datasets for API 3
Roxas2712 Oct 22, 2026
10a6a27
Add owned final-output hooks with scoped GPU state
Roxas2712 Oct 22, 2026
0481a7c
Update output capability assertion and fail GPU probe promptly
Roxas2712 Oct 22, 2026
ce4a825
Add game viewport and window composition contracts
Roxas2712 Oct 22, 2026
18aa200
Integrate Gen1 touch skin parsing and native input ownership
Roxas2712 Oct 28, 2026
f885d62
Expose installed skins through native options and test host ownership
Roxas2712 Oct 28, 2026
ab5b84e
Preserve native pointer ownership and isolate archive test fixtures
Roxas2712 Oct 28, 2026
876385e
Track skin archive fixture and exercise normal options persistence
Roxas2712 Oct 28, 2026
90296f9
Verify custom skin API through actual mod loader and hook chain
Roxas2712 Oct 28, 2026
f275526
Document native skin runtime provenance and remaining acceptance scope
Roxas2712 Oct 28, 2026
9e51cd0
Adapt skin integration to offered upstream viewport and flat options …
Roxas2712 Oct 28, 2026
f32c163
Ship preserved Gen1 touch skin licence in shared payload packer
Roxas2712 Oct 28, 2026
c0b6eb2
Retain contribution and provenance notices in upstream payloads
Roxas2712 Oct 28, 2026
dc29c16
Retain mounted skin archives across real PhysFS library refreshes
Roxas2712 Oct 28, 2026
0dab2c1
Restore native touch haptics preferences and ownership-edge feedback
Roxas2712 Oct 28, 2026
e3faf94
Initialize the upstream haptics fixture system interface
Roxas2712 Oct 28, 2026
c25a8ab
Complete the platform contract in the upstream haptics fixture
Roxas2712 Oct 28, 2026
6c63f3a
Supply real native speed lock owner for offered skin actions
Roxas2712 Oct 28, 2026
5805f05
Use the actual native stack in upstream skin lock contract
Roxas2712 Oct 28, 2026
a3f0d34
Retain required source and visible native launcher credits
Roxas2712 Oct 28, 2026
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
61 changes: 61 additions & 0 deletions .github/workflows/api3-contract.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: API 3 contracts
on:
pull_request:
paths:
- '.github/workflows/api3-contract.yml'
- 'src/**'
- 'tests/api3_contract/**'
- 'tests/engine/api3_*.lua'
- 'tools/api3-contract-check/**'
- 'tools/flag-catalog-check/**'
push:
branches: [main, dev]
paths:
- '.github/workflows/api3-contract.yml'
- 'src/**'
- 'tests/api3_contract/**'
- 'tests/engine/api3_*.lua'
- 'tools/api3-contract-check/**'
- 'tools/flag-catalog-check/**'
permissions:
contents: read
concurrency:
group: api3-contract-${{ github.ref }}
cancel-in-progress: true
jobs:
compare:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
path: gen2
sparse-checkout: |
src
data
tests
tools/api3-contract-check
tools/flag-catalog-check
- uses: actions/checkout@v7
with:
repository: bryanthaboi/gen1recomp
ref: 79ea62f45fb2ea8f65d081a109431e4eb1bbdb36
path: gen1-reference
sparse-checkout: |
src
data
tests
assets/fonts
- name: install LuaJIT
run: sudo apt-get update && sudo apt-get install -y luajit
- name: native flag catalog provenance
run: python3 gen2/tools/flag-catalog-check/generate.py --gen1 gen1-reference
- name: identical mod contracts on both engines
run: >-
python3 gen2/tools/api3-contract-check/check.py
--gen1 gen1-reference --gen2 gen2
--report "${{ runner.temp }}/api3-report.json"
- uses: actions/upload-artifact@v7
with:
name: api3-contract-report
path: ${{ runner.temp }}/api3-report.json
if-no-files-found: error
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,6 @@ mobile/ios/bundle_id.local
# secrets as public -- but GitHub's secret scanning flags it, so it is kept out
# of the repository and injected into release builds instead.
/cloud_clients.lua

# Owned memory-only custom-skin fixture.
!/tests/skin_fs_fixture.lua
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.
21 changes: 21 additions & 0 deletions NOTICE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Native touch-skin provenance

The TouchSkin, DeltaSkin, SkinZip and PdfImage modules, their identified
TouchControls integration and adapted format tests originate in Gen1Recomp
commit 535a5ec088c1ae1bf4d91dd3e35a56f64cf46d91.
Copyright (C) 2026 BOIS CLUB GAMES, LLC. GPLv3 and its Section 7 terms are
retained in licenses/GEN1RECOMP-TOUCH-SKINS.md.

Native host integration and tests: Contributions by Roxas2712 —
https://github.com/Roxas2712

Existing upstream and Gen1 rights and licence grants remain effective; this
notice assigns no other author's work to Roxas2712. No proprietary Gen1
launcher code or third-party bundled skin art is included.

Roxas2712's independently owned additions are offered under
[LICENSE-ROXAS2712.md](LICENSE-ROXAS2712.md), subject to prior grants and
the preserved Gen1 GPL terms. Existing GPL-covered code is not relicensed.

The identified haptic controls in TouchControls.lua are also adapted from the
same Gen1Recomp source under the same preserved GPL/Section7 grant.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# gen2recomp

Based on the Pokemon Gen 1 Recompilation Project by BOIS CLUB GAMES, LLC
(https://github.com/bryanthaboi/gen1recomp).

Contributions by Roxas2712 — https://github.com/Roxas2712.
Newly adapted touch-skin/studio code retains the original GPLv3/Section7
terms in `licenses/GEN1RECOMP-TOUCH-SKINS.md`. Existing author rights and
earlier grants remain effective; see `NOTICE.md` and `LICENSE-ROXAS2712.md`.

<p align="center"><img src="./assets/logo/gen2logo.png"></p>

<p align="center"><img src="./assets/logo/UD.png" width="220"></p>
Expand Down
75 changes: 75 additions & 0 deletions docs/api3-flags.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# API-3 native and private flags

`mod.world:getFlag(reference)` returns a boolean or `nil, reason`.
`setFlag(reference, boolean)` returns `true` or `nil, reason`. Real booleans are
required. The facade follows the current Game/save without bootstrapping one.
Flag reads/writes require a save but can run during menus/scripts; they do not
start an idle-world action. Writes from a rolled-back/reloaded/unloaded owner
are retired. Gen4/5 remain outside the shared API-3 world surface.

## Private flags

`mod:<key>` and `mod.<this-mod-id>.<key>` address the same private flag in
`save.modData[modId].worldFlags`. A foreign `mod.<other-id>.*` reference is
refused. Keys are nonempty strings up to 256 bytes without control characters.
A read does not create storage. A clear removes the key. Malformed stores are
refused without overwriting them. The existing change-only `flag.changed`
payload remains `{name="mod.<modId>.<key>", value=boolean}`.

## Cartridge flags

| Version | Public references | Host storage |
| --- | --- | --- |
| Red/Blue | Known event symbol or its named bit index | Existing `EVENT_*` save.flags key |
| Yellow | Yellow event symbol or its named bit index | Existing `EVENT_*` save.flags key, with Yellow's own bit catalog |
| Gold/Silver | EVENT symbol or whole bit index 0–2047 | `EVENT_G2_%04d`, as used by the VM/save converter |
| Crystal | Whole bit index 0–2047 | Same native numbered namespace; symbolic references explicitly decline, matching the pinned Gen1 API |
| FireRed/Emerald | Known native flag symbol/alias, or a named numeric flag in that version's range | `FLAG_G3_%04X`, as used by the VM/save converter |

Native IDs/symbols are cartridge-specific; no equivalence between the same bit
number in different games is invented. Unknown, fractional, non-finite,
negative, malformed or out-of-range references decline before writes. Special
variables are not a new flag namespace. Prism/Polished Crystal native mappings
are not guessed from Gold; private flags remain available there.

Clearing a native host flag retains `false`, matching native object visibility's
distinction between "cleared" and "untouched". Gen3 synchronizes active object
templates carrying that exact native flag through the host's targeted native
visibility entry; unrelated actors/templates are left alone. Native failures
there can happen after the flag write and are not transactional rollback.

Native `flag.changed` fires only on a true boolean transition. Its name is the
Gen1 symbol, Gen2 bit number, or Gen3 version-catalog name (falling back to the
numeric ID); Gen3 also provides `id`. For Gen3 cross-engine listeners, use
`event.id` for native identity: the pinned Gen1 implementation's native emitter
uses its base FireRed name catalog even on Emerald, so `event.name` is not a
portable label there. The shared fixture consumes `event.id or event.name` on
both engines. This preserves meaningful native identity rather than claiming
all label strings are identical. Reentrant writes from an API-3 flag event or
native visibility callback decline with "world is busy"; reads remain usable.

## Catalog provenance and verification

Generated Red/Yellow/FireRed/Emerald identifier catalogs contain names/numbers
only. No Gen1 engine implementation or ROM is vendored. Gold/Silver reuse the
host's existing Gen2Flags table. The reference is pinned to clean
`bryanthaboi/gen1recomp@79ea62f45fb2ea8f65d081a109431e4eb1bbdb36`.

```sh
luajit tests/engine/api3_flags.lua
python3 tools/flag-catalog-check/generate.py --gen1 /clean/pinned/gen1 --lua luajit
# Add --write to regenerate the deterministic catalogs.
```

The provenance checker verifies every generated row and all 1235 pinned Gold
symbol mappings against the host. CI checks provenance alongside the shared
mod suite. Eight identical public-only mod cases bring that suite to
72 comparisons / 144 isolated loader runs; compare preflight, numeric/symbolic
aliases, booleans, no-op event suppression, public event identity/value and
private ownership. The reference uses actual flag backends with synthetic
world/store setup.

Local checks cover every shipped catalog alias/named numeric entry, the Gen3
VM key conversion and all 2048 Gen2 bits, plus malformed inputs/stores,
owner retirement, reentry and scoped visibility dispatch. These are ROM-free
runtime/store tests, not cartridge story progression or visual gameplay tests.
57 changes: 57 additions & 0 deletions docs/api3-invalidate-map.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# API-3 map invalidation

`mod.world:invalidateMap(mapId)` requests the host's native cache invalidation
and reload for generations 1–3. Capture `mod.world` at entry and call later from
an idle world. Return `true` or `nil, reason`; query availability through
`mod:supports("world", "invalidateMap")`. Gen4/5 decline. API-1/2 behavior and
the portable script vocabulary are unchanged.

```lua
local mod = ...
local world = mod.world
local function refresh(mapId)
return world:invalidateMap(mapId)
end
```

A known map ID is required: a nonempty string up to 256 bytes without control
characters. Invalid or unknown IDs return `nil, "unknown map"`, matching Gen1's
API-3 preflight. Gen3 also resolves unprefixed names using the current version's
FR_/EM_/RU_/SA_ prefix when no exact ID exists. Map IDs remain dataset-specific.

This shares NPC/object/block mutation admission and reentry protection. A save
and topmost idle overworld are required. Scripts, queued/parallel work, player
movement, transitions, menus, link sessions and controller locks refuse before
cache writes. Missing native reload support declines. Reading the facade never
constructs Game. Rollback/reload/teardown retire retained mutation facades.

The host's native reloadMap invalidates the target and resident neighbor cache
entries. For the active map it uses setMap with seamless reload, current player
cell/facing and keepMusic. If the retained player cell no longer fits the new
geometry, native reload sends the player to the heal point. Runtime map/actor
instance identity can change, so obtain fresh NPC handles after a reload.
Inactive invalidation does not move the player or force an unrelated active
map reload. Rendering and map lifecycle events remain native, not a new common
renderer/cache implementation. Successful host invalidation emits map.reloaded
with mapId and reason="invalidate". Pinned Gen1's Gen2 backend does not emit
that event for inactive invalidation; this native difference is retained.

This is a cache/instance operation, not a content-write API. Permanent map
changes belong in content definitions. A native failure returns nil with its
reason but may occur after cache invalidation; already entered native effects
are not transactionally rolled back.

## Verification

Run `luajit tests/engine/api3_invalidate.lua` and the pinned checker documented
in [API-3 portability](api3-portability.md). Eight identical public mod cases
extend the full checker to 64 comparisons / 128 isolated loader runs. Real
loaders/native facades compare preflight, active reload, position retention,
notification and inactive-map acceptance; reload timing is a driver seam.

Host tests additionally run actual OverworldState.reloadMap and
MapLoader.invalidate against a synthetic cache, with the setMap/render entry
instrumented. Verify target/neighbor eviction, seamless/music options, valid
player retention, heal-point fallback, reentry, failure/guard release, busy
worlds and retired owners. No ROM import or rendered gameplay equivalence is
claimed.
Loading