mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-28 18:06:09 +02:00
Add Xbox UWP build workflow
This commit is contained in:
@@ -181,6 +181,85 @@ jobs:
|
||||
if-no-files-found: error
|
||||
retention-days: 7
|
||||
|
||||
xbox-uwp-changes:
|
||||
name: detect Xbox UWP changes
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
changed: ${{ steps.paths.outputs.changed }}
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- id: paths
|
||||
env:
|
||||
BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }}
|
||||
HEAD_SHA: ${{ github.sha }}
|
||||
run: |
|
||||
if [ -z "$BASE_SHA" ] || [ "$BASE_SHA" = "0000000000000000000000000000000000000000" ]; then
|
||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
if git diff --name-only "$BASE_SHA" "$HEAD_SHA" | grep -Eq '^(ports/uwp/|scripts/build_xbox_uwp\.sh$|scripts/xbox-uwp/|scripts/pack_love\.sh$|\.github/workflows/(ci|release)\.yml$|src/core/Platform\.lua$|src/import/(CacheFs|RomImporter)\.lua$|src/update/Check\.lua$|tests/engine/(platform_nx|uwp_native_picker)_test\.lua$|tests/rom_importer_double_pick_test\.lua$)'; then
|
||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "changed=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
xbox-uwp-selftest:
|
||||
name: Xbox UWP offline selftest
|
||||
needs: xbox-uwp-changes
|
||||
if: needs.xbox-uwp-changes.outputs.changed == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Xbox UWP offline selftest
|
||||
run: bash scripts/xbox-uwp/selftest_build_xbox_uwp.sh
|
||||
- name: Build shared payload
|
||||
run: |
|
||||
scripts/pack_love.sh \
|
||||
--output .bazinga/work/ci-game.love \
|
||||
--listing .bazinga/work/ci-love-listing.txt \
|
||||
--version 0.0.0
|
||||
- name: Upload shared payload
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: gen1recomp-xbox-uwp-payload
|
||||
path: .bazinga/work/ci-game.love
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
xbox-uwp-build:
|
||||
name: Xbox UWP build
|
||||
needs: [xbox-uwp-changes, xbox-uwp-selftest]
|
||||
if: |
|
||||
always()
|
||||
&& needs.xbox-uwp-changes.outputs.changed == 'true'
|
||||
&& needs.xbox-uwp-selftest.result == 'success'
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Download shared payload
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: gen1recomp-xbox-uwp-payload
|
||||
path: .bazinga/work
|
||||
- name: Build Xbox UWP package
|
||||
shell: bash
|
||||
run: |
|
||||
bash scripts/build_xbox_uwp.sh \
|
||||
--release \
|
||||
--version 0.0.0 \
|
||||
--game-love .bazinga/work/ci-game.love
|
||||
- name: Upload Xbox UWP package
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: gen1recomp-xbox-uwp
|
||||
path: |
|
||||
dist/xbox-uwp/gen1recomp-0.0.0-xbox-uwp.zip
|
||||
dist/xbox-uwp/gen1recomp-0.0.0-xbox-uwp.zip.sha256
|
||||
if-no-files-found: error
|
||||
retention-days: 7
|
||||
|
||||
headless:
|
||||
name: headless suites (no ROM)
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
+150
-28
@@ -1,9 +1,9 @@
|
||||
name: Release
|
||||
|
||||
# Builds the macOS, Windows, and Linux desktop apps, an Android APK, an iOS
|
||||
# IPA, a Nintendo Switch SD-ready zip (experimental), and the Anbernic RG34XXSP
|
||||
# (Stock OS 64-bit MOD / PortMaster) port on the self-hosted Mac runner, and
|
||||
# publishes them as a GitHub Release.
|
||||
# IPA, a Nintendo Switch SD-ready zip (experimental), Xbox UWP, and the Anbernic
|
||||
# RG34XXSP (Stock OS 64-bit MOD / PortMaster) port, then publishes them as a
|
||||
# GitHub Release.
|
||||
#
|
||||
# Versioning:
|
||||
# - First ever release is 0.1.0.
|
||||
@@ -43,22 +43,17 @@ concurrency:
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ${{ fromJSON(github.repository == 'bryanthaboi/gen1recomp' && '["self-hosted", "macOS"]' || '"macos-latest"') }}
|
||||
|
||||
version:
|
||||
name: determine release version
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.ver.outputs.version }}
|
||||
tag: ${{ steps.ver.outputs.tag }}
|
||||
steps:
|
||||
# The self-hosted runner lives under the machine owner's home
|
||||
# directory; mask it first so absolute paths in every later step's
|
||||
# output show up as *** in the public workflow logs.
|
||||
- name: Mask runner paths
|
||||
run: echo "::add-mask::$HOME"
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
- name: Determine version
|
||||
id: ver
|
||||
env:
|
||||
@@ -66,7 +61,6 @@ jobs:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
semver_re='^[0-9]+\.[0-9]+\.[0-9]+$'
|
||||
|
||||
# 1) Explicit override from a manual run.
|
||||
@@ -96,7 +90,6 @@ jobs:
|
||||
| grep -E "$semver_re" \
|
||||
| sort -t. -k1,1n -k2,2n -k3,3n \
|
||||
| tail -1 || true)"
|
||||
|
||||
if [ -z "$latest" ]; then
|
||||
version="0.1.0"
|
||||
echo "No existing release tag; starting at $version"
|
||||
@@ -124,10 +117,127 @@ jobs:
|
||||
echo "::error::Release $tag already exists. Pick a different version."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "version=$version" >> "$GITHUB_OUTPUT"
|
||||
echo "tag=$tag" >> "$GITHUB_OUTPUT"
|
||||
|
||||
love-payload:
|
||||
name: build release game.love
|
||||
needs: version
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Build shared payload
|
||||
run: |
|
||||
scripts/pack_love.sh \
|
||||
--output dist/payload/game.love \
|
||||
--listing dist/payload/love-listing.txt \
|
||||
--version "${{ needs.version.outputs.version }}"
|
||||
- name: Upload shared payload
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: gen1recomp-release-love
|
||||
path: dist/payload/game.love
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
xbox-uwp:
|
||||
name: build Xbox UWP release
|
||||
needs: [version, love-payload]
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Download shared payload
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: gen1recomp-release-love
|
||||
path: .bazinga/work
|
||||
- name: Prepare signing certificate
|
||||
shell: pwsh
|
||||
env:
|
||||
CERTIFICATE_BASE64: ${{ secrets.XBOX_UWP_SIGNING_CERTIFICATE }}
|
||||
CERTIFICATE_PASSWORD: ${{ secrets.XBOX_UWP_SIGNING_PASSWORD }}
|
||||
CANONICAL_REPOSITORY: ${{ github.repository == 'bryanthaboi/gen1recomp' }}
|
||||
run: |
|
||||
if ($env:CANONICAL_REPOSITORY -eq 'true' -and
|
||||
[string]::IsNullOrWhiteSpace($env:CERTIFICATE_BASE64)) {
|
||||
throw 'XBOX_UWP_SIGNING_CERTIFICATE is not configured.'
|
||||
}
|
||||
if ([string]::IsNullOrWhiteSpace($env:CERTIFICATE_BASE64)) {
|
||||
"UWP_PUBLISHER=CN=Gen1Recomp" | Out-File $env:GITHUB_ENV -Append
|
||||
exit 0
|
||||
}
|
||||
$pfx = Join-Path $env:RUNNER_TEMP 'gen1recomp-uwp.pfx'
|
||||
[IO.File]::WriteAllBytes($pfx, [Convert]::FromBase64String($env:CERTIFICATE_BASE64))
|
||||
$flags = [Security.Cryptography.X509Certificates.X509KeyStorageFlags]::EphemeralKeySet
|
||||
$cert = [Security.Cryptography.X509Certificates.X509Certificate2]::new(
|
||||
$pfx, $env:CERTIFICATE_PASSWORD, $flags)
|
||||
$cer = Join-Path $env:RUNNER_TEMP 'gen1recomp-uwp.cer'
|
||||
[IO.File]::WriteAllBytes(
|
||||
$cer,
|
||||
$cert.Export([Security.Cryptography.X509Certificates.X509ContentType]::Cert))
|
||||
Import-Certificate -FilePath $cer -CertStoreLocation Cert:\LocalMachine\TrustedPeople | Out-Null
|
||||
"UWP_PFX=$pfx" | Out-File $env:GITHUB_ENV -Append
|
||||
"UWP_CERT_THUMBPRINT=$($cert.Thumbprint)" | Out-File $env:GITHUB_ENV -Append
|
||||
"UWP_PUBLISHER=$($cert.Subject)" | Out-File $env:GITHUB_ENV -Append
|
||||
- name: Build Xbox UWP package
|
||||
shell: bash
|
||||
run: |
|
||||
bash scripts/build_xbox_uwp.sh \
|
||||
--release \
|
||||
--version "${{ needs.version.outputs.version }}" \
|
||||
--publisher "$UWP_PUBLISHER" \
|
||||
--game-love .bazinga/work/game.love
|
||||
- name: Sign and stage Xbox UWP release
|
||||
shell: pwsh
|
||||
env:
|
||||
CERTIFICATE_PASSWORD: ${{ secrets.XBOX_UWP_SIGNING_PASSWORD }}
|
||||
run: |
|
||||
if (-not $env:UWP_PFX) {
|
||||
exit 0
|
||||
}
|
||||
scripts/xbox-uwp/stage_release.ps1 `
|
||||
-Version '${{ needs.version.outputs.version }}' `
|
||||
-Configuration Release `
|
||||
-BuildInfo .bazinga/work/xbox-uwp-build-info.json `
|
||||
-CertificatePath $env:UWP_PFX `
|
||||
-CertificatePassword $env:CERTIFICATE_PASSWORD
|
||||
- name: Upload Xbox UWP release
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: gen1recomp-xbox-uwp-release
|
||||
path: |
|
||||
dist/xbox-uwp/gen1recomp-${{ needs.version.outputs.version }}-xbox-uwp.zip
|
||||
dist/xbox-uwp/gen1recomp-${{ needs.version.outputs.version }}-xbox-uwp.zip.sha256
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
- name: Remove signing certificate
|
||||
if: always()
|
||||
shell: pwsh
|
||||
run: |
|
||||
if ($env:UWP_CERT_THUMBPRINT) {
|
||||
Remove-Item "Cert:\LocalMachine\TrustedPeople\$env:UWP_CERT_THUMBPRINT" -ErrorAction SilentlyContinue
|
||||
}
|
||||
if ($env:UWP_PFX) {
|
||||
Remove-Item $env:UWP_PFX -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
release:
|
||||
needs: [version, xbox-uwp]
|
||||
runs-on: ${{ fromJSON(github.repository == 'bryanthaboi/gen1recomp' && '["self-hosted", "macOS"]' || '"macos-latest"') }}
|
||||
|
||||
steps:
|
||||
# The self-hosted runner lives under the machine owner's home
|
||||
# directory; mask it first so absolute paths in every later step's
|
||||
# output show up as *** in the public workflow logs.
|
||||
- name: Mask runner paths
|
||||
run: echo "::add-mask::$HOME"
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
- name: Import signing certificate into a temporary keychain
|
||||
if: github.repository == 'bryanthaboi/gen1recomp'
|
||||
run: |
|
||||
@@ -172,12 +282,12 @@ jobs:
|
||||
# notarize separately below so it uses secret credentials, not a
|
||||
# login-keychain profile. "all" also builds the Linux AppImage,
|
||||
# which needs no signing/notarization.
|
||||
scripts/build.sh all --version "${{ steps.ver.outputs.version }}" --no-notarize
|
||||
scripts/build.sh all --version "${{ needs.version.outputs.version }}" --no-notarize
|
||||
|
||||
- name: Build Android
|
||||
run: |
|
||||
set -euo pipefail
|
||||
scripts/build_android.sh --version "${{ steps.ver.outputs.version }}"
|
||||
scripts/build_android.sh --version "${{ needs.version.outputs.version }}"
|
||||
|
||||
- name: Install xcbeautify
|
||||
run: |
|
||||
@@ -191,10 +301,10 @@ jobs:
|
||||
set -euo pipefail
|
||||
if [ "$CANONICAL_REPOSITORY" = true ]; then
|
||||
scripts/build_ios.sh --fetch --device --release \
|
||||
--version "${{ steps.ver.outputs.version }}"
|
||||
--version "${{ needs.version.outputs.version }}"
|
||||
else
|
||||
scripts/build_ios.sh --fetch --release \
|
||||
--version "${{ steps.ver.outputs.version }}"
|
||||
--version "${{ needs.version.outputs.version }}"
|
||||
fi
|
||||
|
||||
- name: Build Switch
|
||||
@@ -206,14 +316,14 @@ jobs:
|
||||
# Needs native switch-tools (nacptool/elf2nro) and/or Docker on the
|
||||
# Mac self-hosted runner; see docs/switch-build.md.
|
||||
scripts/build_switch.sh --fetch --fused \
|
||||
--version "${{ steps.ver.outputs.version }}"
|
||||
--version "${{ needs.version.outputs.version }}"
|
||||
|
||||
- name: Build Anbernic RG34XXSP port
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# Self-contained aarch64 PortMaster-style pack; pulls the LÖVE 11.5
|
||||
# runtime from PortMaster-GUI, so it needs no signing/notarization.
|
||||
./build-rg34xxsp.sh --version "${{ steps.ver.outputs.version }}"
|
||||
./build-rg34xxsp.sh --version "${{ needs.version.outputs.version }}"
|
||||
|
||||
- name: Notarize & staple macOS app
|
||||
if: github.repository == 'bryanthaboi/gen1recomp'
|
||||
@@ -250,12 +360,19 @@ jobs:
|
||||
ditto -c -k --sequesterRsrc --keepParent "$app" "$zip"
|
||||
echo "Notarized + stapled ✓"
|
||||
|
||||
- name: Download Xbox UWP release
|
||||
if: github.repository == 'bryanthaboi/gen1recomp'
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: gen1recomp-xbox-uwp-release
|
||||
path: dist/xbox-uwp
|
||||
|
||||
- name: Stage release assets
|
||||
if: github.repository == 'bryanthaboi/gen1recomp'
|
||||
id: assets
|
||||
run: |
|
||||
set -euo pipefail
|
||||
v="${{ steps.ver.outputs.version }}"
|
||||
v="${{ needs.version.outputs.version }}"
|
||||
outdir="dist/release"
|
||||
rm -rf "$outdir"
|
||||
mkdir -p "$outdir"
|
||||
@@ -276,6 +393,10 @@ jobs:
|
||||
# Local fused .nro stays under dist/switch/ for PR CI / debug; release
|
||||
# publishes the SD-ready zip only.
|
||||
|
||||
uwp="dist/xbox-uwp/gen1recomp-${v}-xbox-uwp.zip"
|
||||
[ -f "$uwp" ] || { echo "::error::$uwp not found (expected from the Xbox UWP job)"; exit 1; }
|
||||
cp "$uwp" "$outdir/gen1recomp-${v}-xbox-uwp.zip"
|
||||
|
||||
# Anbernic handheld port (suffix names the CFW it targets, so a
|
||||
# future RG35XX/other-CFW pack can ship alongside it).
|
||||
rg34="dist/rg34xxsp/gen1recomp-rg34xxsp-stockos64-mod.zip"
|
||||
@@ -302,8 +423,8 @@ jobs:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
v="${{ steps.ver.outputs.version }}"
|
||||
tag="${{ steps.ver.outputs.tag }}"
|
||||
v="${{ needs.version.outputs.version }}"
|
||||
tag="${{ needs.version.outputs.tag }}"
|
||||
|
||||
# Issues this release closes. Three sources, deduped by number:
|
||||
# 1. GitHub's own "closing issues" links on every PR whose
|
||||
@@ -394,6 +515,7 @@ jobs:
|
||||
"dist/release/gen1recomp-${v}-android.apk"
|
||||
"dist/release/gen1recomp-${v}-ios.ipa"
|
||||
"dist/release/gen1recomp-${v}-switch.zip"
|
||||
"dist/release/gen1recomp-${v}-xbox-uwp.zip"
|
||||
"dist/release/gen1recomp-${v}-rg34xxsp-stockos64-mod.zip"
|
||||
"dist/release/gen1recomp-${v}.love"
|
||||
"dist/release/sha256sums.txt"
|
||||
@@ -411,7 +533,7 @@ jobs:
|
||||
if: github.repository == 'bryanthaboi/gen1recomp'
|
||||
run: |
|
||||
set -euo pipefail
|
||||
v="${{ steps.ver.outputs.version }}"
|
||||
v="${{ needs.version.outputs.version }}"
|
||||
ipa="dist/release/gen1recomp-${v}-ios.ipa"
|
||||
app_repo="mobile/ios/app-repo.json"
|
||||
[ -f "$ipa" ] || { echo "::error::$ipa not found"; exit 1; }
|
||||
|
||||
+61
-11
@@ -19,7 +19,8 @@ The tested toolchain is:
|
||||
- C++ Universal Windows Platform tools
|
||||
- Windows 11 SDK `10.0.26100.0`
|
||||
- CMake 3.24 or newer
|
||||
- Git
|
||||
- Git for Windows
|
||||
- Info-ZIP `zip` and `unzip`
|
||||
|
||||
Use Visual Studio Installer to add **Universal Windows Platform development**, the v143 C++ tools, CMake tools for Windows, and Windows SDK `10.0.26100.0`.
|
||||
|
||||
@@ -30,10 +31,10 @@ build.
|
||||
|
||||
## Rebuild the Dependencies
|
||||
|
||||
Run the dependency rebuild from `ports/uwp`:
|
||||
Run the dependency rebuild from the repository root:
|
||||
|
||||
```powershell
|
||||
.\scripts\rebuild-dependencies.ps1
|
||||
.\scripts\xbox-uwp\rebuild_dependencies.ps1
|
||||
```
|
||||
|
||||
The script clones the pinned SDL2, LÖVE, LuaJIT, vcpkg, depot_tools, and ANGLE
|
||||
@@ -46,24 +47,73 @@ The generated source checkouts are ignored by Git. A fresh ANGLE sync is about
|
||||
10 GB, so allow at least 20 GB of free disk space for all sources and build
|
||||
outputs. Use `-SkipAngle` to retain the existing pinned ANGLE runtime while
|
||||
rebuilding SDL2, LÖVE, LuaJIT, and the vcpkg libraries. Use `-SkipPackage` when
|
||||
only the dependency bundle needs to be refreshed.
|
||||
only the dependency bundle needs to be refreshed. The rebuild stops if a source
|
||||
checkout has local changes. Remove that generated `source` directory to restore
|
||||
the pinned revision.
|
||||
|
||||
## Build the MSIX
|
||||
|
||||
Build the game package from `ports/uwp`:
|
||||
Run the Xbox build from Git Bash at the repository root:
|
||||
|
||||
```powershell
|
||||
Set-Location "ports\uwp"
|
||||
cmake --preset uwp-release
|
||||
cmake --build --preset uwp-release
|
||||
```bash
|
||||
scripts/build_xbox_uwp.sh --release --version 1.2.3
|
||||
```
|
||||
|
||||
The build creates `gen1recomp.love`, links the UWP host, and stages LÖVE, LuaJIT, SDL2, ANGLE, and the vcpkg runtime DLLs.
|
||||
The build uses `scripts/pack_love.sh` to create and verify the same ROM-free
|
||||
`game.love` payload used by the other release targets. It then links the UWP
|
||||
host and stages LÖVE, LuaJIT, SDL2, ANGLE, and the vcpkg runtime DLLs.
|
||||
|
||||
Use `--relwithdebinfo` for a package with symbols. To package a `.love` produced
|
||||
by another build or downloaded from CI, pass `--game-love path/to/game.love`.
|
||||
The upstream `X.Y.Z` release becomes `X.Y.Z.0` in the generated MSIX manifest.
|
||||
Neither the manifest template nor `src/core/Version.lua` is edited in place.
|
||||
|
||||
The manifest publisher must match the signing certificate subject. Pass it
|
||||
when preparing a signed package:
|
||||
|
||||
```bash
|
||||
scripts/build_xbox_uwp.sh --release --version 1.2.3 \
|
||||
--publisher "CN=Gen1Recomp"
|
||||
```
|
||||
|
||||
The normal build is unsigned. Release CI supplies the private PFX and password
|
||||
from `XBOX_UWP_SIGNING_CERTIFICATE` and `XBOX_UWP_SIGNING_PASSWORD`; neither may
|
||||
be committed. The public certificate is safe to include with the release.
|
||||
|
||||
Run the offline packaging checks from Git Bash:
|
||||
|
||||
```bash
|
||||
bash scripts/xbox-uwp/selftest_build_xbox_uwp.sh
|
||||
```
|
||||
|
||||
## Build Output
|
||||
|
||||
The Release package lands under:
|
||||
Visual Studio package output lands under:
|
||||
|
||||
```text
|
||||
ports\uwp\build\release\AppPackages\Gen1RecompUWP
|
||||
```
|
||||
|
||||
The build also stages the distributable archive and checksum under:
|
||||
|
||||
```text
|
||||
dist\xbox-uwp\gen1recomp-X.Y.Z-xbox-uwp.zip
|
||||
dist\xbox-uwp\gen1recomp-X.Y.Z-xbox-uwp.zip.sha256
|
||||
```
|
||||
|
||||
The archive contains the MSIX, framework dependencies, build provenance and,
|
||||
for a signed release, the public certificate. The third-party notices are
|
||||
packaged inside the MSIX. Install the MSIX and dependency packages through
|
||||
Xbox Device Portal.
|
||||
|
||||
## Runtime Data
|
||||
|
||||
The package contains no ROM, generated cache, save or mod data. The Xbox file
|
||||
picker copies user-selected files into LocalState and the launcher imports them
|
||||
from there. Saves, ROM cache and installed mods remain under the LÖVE save
|
||||
directory in LocalState.
|
||||
|
||||
LuaJIT requires the `codeGeneration` capability. `removableStorage` exposes
|
||||
external media to the Xbox picker. The network capabilities support relay play
|
||||
and direct hosting. The package does not request full trust or broad filesystem
|
||||
access.
|
||||
|
||||
@@ -12,6 +12,31 @@ set(SDL2_ROOT "${THIRD_PARTY_ROOT}/sdl2")
|
||||
set(ANGLE_ROOT "${THIRD_PARTY_ROOT}/angle")
|
||||
set(RUNTIME_ROOT "${THIRD_PARTY_ROOT}/runtime")
|
||||
|
||||
set(GEN1RECOMP_VERSION "0.0.0" CACHE STRING "Gen1Recomp release version")
|
||||
if(NOT GEN1RECOMP_VERSION MATCHES "^[0-9]+\\.[0-9]+\\.[0-9]+$")
|
||||
message(FATAL_ERROR "GEN1RECOMP_VERSION must use X.Y.Z format.")
|
||||
endif()
|
||||
string(REPLACE "." ";" VERSION_PARTS "${GEN1RECOMP_VERSION}")
|
||||
foreach(part IN LISTS VERSION_PARTS)
|
||||
if(part GREATER 65535)
|
||||
message(FATAL_ERROR "MSIX version components cannot exceed 65535.")
|
||||
endif()
|
||||
endforeach()
|
||||
set(GEN1RECOMP_UWP_PUBLISHER "CN=Gen1Recomp" CACHE STRING
|
||||
"Publisher subject from the MSIX signing certificate")
|
||||
set(UWP_PUBLISHER_XML "${GEN1RECOMP_UWP_PUBLISHER}")
|
||||
string(REPLACE "&" "&" UWP_PUBLISHER_XML "${UWP_PUBLISHER_XML}")
|
||||
string(REPLACE "\"" """ UWP_PUBLISHER_XML "${UWP_PUBLISHER_XML}")
|
||||
string(REPLACE "<" "<" UWP_PUBLISHER_XML "${UWP_PUBLISHER_XML}")
|
||||
string(REPLACE ">" ">" UWP_PUBLISHER_XML "${UWP_PUBLISHER_XML}")
|
||||
set(UWP_PACKAGE_VERSION "${GEN1RECOMP_VERSION}.0")
|
||||
set(PACKAGE_MANIFEST "${CMAKE_CURRENT_BINARY_DIR}/Package.appxmanifest")
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_LIST_DIR}/Package.appxmanifest.in"
|
||||
"${PACKAGE_MANIFEST}"
|
||||
@ONLY
|
||||
)
|
||||
|
||||
set(REQUIRED_FILES
|
||||
"${THIRD_PARTY_ROOT}/manifest.json"
|
||||
"${LOVE_ROOT}/lib/lovestatic.lib"
|
||||
@@ -32,19 +57,28 @@ foreach(path IN LISTS REQUIRED_FILES)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(GEN1RECOMP_LOVE "${GAME_ROOT}/.bazinga/work/game.love" CACHE FILEPATH
|
||||
"Path to the game.love payload produced by scripts/pack_love.sh")
|
||||
if(NOT EXISTS "${GEN1RECOMP_LOVE}")
|
||||
message(FATAL_ERROR
|
||||
"Missing game.love payload: ${GEN1RECOMP_LOVE}\n"
|
||||
"Build it with scripts/build_xbox_uwp.sh or scripts/pack_love.sh.")
|
||||
endif()
|
||||
|
||||
set(GAME_ARCHIVE "${CMAKE_CURRENT_BINARY_DIR}/gen1recomp.love")
|
||||
set_source_files_properties("${GAME_ARCHIVE}" PROPERTIES GENERATED TRUE)
|
||||
add_custom_target(gen1recomp_love ALL
|
||||
COMMAND powershell -NoProfile -ExecutionPolicy Bypass -File
|
||||
"${CMAKE_CURRENT_LIST_DIR}/scripts/package-game.ps1"
|
||||
-SourceRoot "${GAME_ROOT}" -Output "${GAME_ARCHIVE}"
|
||||
BYPRODUCTS "${GAME_ARCHIVE}"
|
||||
add_custom_command(
|
||||
OUTPUT "${GAME_ARCHIVE}"
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
|
||||
"${GEN1RECOMP_LOVE}" "${GAME_ARCHIVE}"
|
||||
DEPENDS "${GEN1RECOMP_LOVE}"
|
||||
VERBATIM
|
||||
)
|
||||
add_custom_target(gen1recomp_love ALL DEPENDS "${GAME_ARCHIVE}")
|
||||
set_source_files_properties("${GAME_ARCHIVE}" PROPERTIES GENERATED TRUE)
|
||||
|
||||
add_custom_target(verify_uwp_dependencies
|
||||
COMMAND powershell -NoProfile -ExecutionPolicy Bypass -File
|
||||
"${CMAKE_CURRENT_LIST_DIR}/scripts/verify-dependencies.ps1"
|
||||
"${GAME_ROOT}/scripts/xbox-uwp/verify_dependencies.ps1"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
@@ -53,6 +87,7 @@ add_dependencies(${PROJECT_NAME} gen1recomp_love verify_uwp_dependencies)
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
CXX_STANDARD 17
|
||||
CXX_STANDARD_REQUIRED YES
|
||||
VS_GLOBAL_DefaultLanguage "en-US"
|
||||
VS_SDK_REFERENCES "Microsoft.VCLibs, Version=14.0"
|
||||
)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE "${SDL2_ROOT}/include/SDL2")
|
||||
@@ -65,7 +100,7 @@ target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
)
|
||||
|
||||
set(PACKAGE_ROOT_FILES
|
||||
"${CMAKE_CURRENT_LIST_DIR}/Package.appxmanifest"
|
||||
"${PACKAGE_MANIFEST}"
|
||||
"${GAME_ARCHIVE}"
|
||||
"${LOVE_ROOT}/bin/love.dll"
|
||||
"${LOVE_ROOT}/bin/lua51.dll"
|
||||
@@ -74,6 +109,7 @@ set(PACKAGE_ROOT_FILES
|
||||
"${ANGLE_ROOT}/bin/libGLESv2.dll"
|
||||
"${ANGLE_ROOT}/bin/d3dcompiler_47.dll"
|
||||
)
|
||||
set_source_files_properties("${PACKAGE_MANIFEST}" PROPERTIES GENERATED TRUE)
|
||||
|
||||
set(RUNTIME_NAMES
|
||||
brotlicommon.dll brotlidec.dll bz2.dll fmt.dll freetype.dll libpng16.dll
|
||||
@@ -98,4 +134,16 @@ set_source_files_properties(${PACKAGE_ASSETS} PROPERTIES
|
||||
VS_DEPLOYMENT_CONTENT TRUE
|
||||
VS_DEPLOYMENT_LOCATION "Assets"
|
||||
)
|
||||
target_sources(${PROJECT_NAME} PRIVATE ${PACKAGE_ROOT_FILES} ${PACKAGE_ASSETS})
|
||||
|
||||
file(GLOB PACKAGE_LICENSES CONFIGURE_DEPENDS "${THIRD_PARTY_ROOT}/licenses/*.txt")
|
||||
set_source_files_properties(${PACKAGE_LICENSES} PROPERTIES
|
||||
VS_TOOL_OVERRIDE "Content"
|
||||
VS_COPY_TO_OUT_DIR Always
|
||||
VS_DEPLOYMENT_CONTENT TRUE
|
||||
VS_DEPLOYMENT_LOCATION "licenses"
|
||||
)
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
${PACKAGE_ROOT_FILES}
|
||||
${PACKAGE_ASSETS}
|
||||
${PACKAGE_LICENSES}
|
||||
)
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package
|
||||
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
||||
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
|
||||
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
|
||||
IgnorableNamespaces="uap mp rescap">
|
||||
<Identity Name="Gen1RecompUWP" Publisher="CN=Caorthann" Version="0.3.0.0" />
|
||||
IgnorableNamespaces="uap mp">
|
||||
<Identity Name="Gen1RecompUWP" Publisher="@UWP_PUBLISHER_XML@" Version="@UWP_PACKAGE_VERSION@" />
|
||||
<mp:PhoneIdentity PhoneProductId="5074018d-a46b-4dd3-b7fa-93a1e39858ad" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||
<Properties>
|
||||
<DisplayName>Gen1Recomp</DisplayName>
|
||||
@@ -37,10 +36,8 @@
|
||||
<Capabilities>
|
||||
<Capability Name="internetClient" />
|
||||
<Capability Name="internetClientServer" />
|
||||
<Capability Name="privateNetworkClientServer" />
|
||||
<Capability Name="codeGeneration" />
|
||||
<uap:Capability Name="removableStorage" />
|
||||
<rescap:Capability Name="runFullTrust" />
|
||||
<rescap:Capability Name="broadFileSystemAccess" />
|
||||
<rescap:Capability Name="expandedResources" />
|
||||
</Capabilities>
|
||||
</Package>
|
||||
@@ -26,6 +26,5 @@ int runLove(int, char **)
|
||||
int CALLBACK WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
|
||||
{
|
||||
SDL_SetHint(SDL_HINT_WINRT_HANDLE_BACK_BUTTON, "1");
|
||||
OutputDebugStringA("Gen1Recomp UWP startup\n");
|
||||
return SDL_WinRTRunApp(runLove, nullptr);
|
||||
}
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
param(
|
||||
[Parameter(Mandatory = $true)][string]$SourceRoot,
|
||||
[Parameter(Mandatory = $true)][string]$Output
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$source = (Resolve-Path -LiteralPath $SourceRoot).Path
|
||||
$required = @('main.lua', 'conf.lua', 'tools/rom_manifest.json')
|
||||
$allowedRoots = @('assets/', 'data/', 'mods/', 'src/', 'tools/rom_manifest')
|
||||
$forbidden = '(?i)(^|/)(assets/generated|data/generated|build|dist|ports|mobile|tests?)(/|$)|\.(gb|gbc|sav|srm)$'
|
||||
|
||||
$tracked = & git -C $source ls-files
|
||||
if ($LASTEXITCODE -ne 0) { throw 'git ls-files failed' }
|
||||
|
||||
$entries = $tracked |
|
||||
ForEach-Object { $_.Replace('\', '/') } |
|
||||
Where-Object {
|
||||
$path = $_
|
||||
(($required -contains $path) -or ($allowedRoots | Where-Object { $path.StartsWith($_) })) -and
|
||||
$path -notmatch $forbidden
|
||||
} |
|
||||
Sort-Object -Unique
|
||||
|
||||
foreach ($path in $required) {
|
||||
if ($entries -notcontains $path) { throw "Required game file is missing from archive input: $path" }
|
||||
}
|
||||
|
||||
$parent = Split-Path -Parent $Output
|
||||
New-Item -ItemType Directory -Force -Path $parent | Out-Null
|
||||
if (Test-Path -LiteralPath $Output) { Remove-Item -LiteralPath $Output -Force }
|
||||
|
||||
Add-Type -AssemblyName System.IO.Compression
|
||||
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
||||
$archive = [System.IO.Compression.ZipFile]::Open($Output, 'Create')
|
||||
try {
|
||||
foreach ($relative in $entries) {
|
||||
$full = Join-Path $source $relative
|
||||
if (-not (Test-Path -LiteralPath $full -PathType Leaf)) { throw "Tracked file is missing: $relative" }
|
||||
$entry = $archive.CreateEntry($relative, [System.IO.Compression.CompressionLevel]::Optimal)
|
||||
$entry.LastWriteTime = [DateTimeOffset]'2000-01-01T00:00:00Z'
|
||||
$input = [System.IO.File]::OpenRead($full)
|
||||
$outputStream = $entry.Open()
|
||||
try { $input.CopyTo($outputStream) } finally { $outputStream.Dispose(); $input.Dispose() }
|
||||
}
|
||||
} finally {
|
||||
$archive.Dispose()
|
||||
}
|
||||
|
||||
Write-Host "Created $Output with $($entries.Count) tracked, ROM-free entries."
|
||||
@@ -1,34 +0,0 @@
|
||||
param(
|
||||
[string]$Manifest = (Join-Path $PSScriptRoot "..\third_party\manifest.json")
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$manifestPath = (Resolve-Path $Manifest).Path
|
||||
$thirdPartyRoot = Split-Path -Parent $manifestPath
|
||||
$metadata = Get-Content -Raw $manifestPath | ConvertFrom-Json
|
||||
|
||||
foreach ($file in $metadata.files) {
|
||||
$path = Join-Path $thirdPartyRoot $file.path
|
||||
if (-not (Test-Path -LiteralPath $path -PathType Leaf)) {
|
||||
throw "Missing UWP dependency: $($file.path)"
|
||||
}
|
||||
|
||||
$stream = [System.IO.File]::OpenRead($path)
|
||||
try {
|
||||
$sha256 = [System.Security.Cryptography.SHA256]::Create()
|
||||
try {
|
||||
$hash = $sha256.ComputeHash($stream)
|
||||
$actual = [System.BitConverter]::ToString($hash).Replace("-", "")
|
||||
} finally {
|
||||
$sha256.Dispose()
|
||||
}
|
||||
} finally {
|
||||
$stream.Dispose()
|
||||
}
|
||||
if ($actual -ne $file.sha256) {
|
||||
throw "UWP dependency hash mismatch: $($file.path)"
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Verified $($metadata.files.Count) UWP dependency files."
|
||||
Vendored
+1
-1
@@ -8,4 +8,4 @@ This directory contains the complete x64 UWP Release dependency bundle used by t
|
||||
- `runtime` contains the codec, font, compression, and audio DLLs used by LÖVE.
|
||||
- `licenses` contains the corresponding third party notices.
|
||||
|
||||
`manifest.json` pins the source revisions and SHA-256 hashes. Run `../scripts/verify-dependencies.ps1` after updating any dependency.
|
||||
`manifest.json` pins the source revisions and SHA-256 hashes. Run `scripts/xbox-uwp/verify_dependencies.ps1` from the repository root after updating any dependency.
|
||||
|
||||
Vendored
+302
-302
@@ -90,88 +90,296 @@
|
||||
"sha256": "A05F99734F7C4822FEFC12B367AF21FD0976ED6608752FB1E1E80B6ECE7ECBBB"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_scancode.h",
|
||||
"sha256": "EB14F3CEDDE58358F6456D185F473D7551E8234DE260151AD0319861FF1444C2"
|
||||
"path": "angle/bin/libEGL.dll",
|
||||
"sha256": "B0E0C6BAC9D9F0F084DC8F56083A2EEFFB866C0629A64D52B5E33616B4F90CBE"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_rwops.h",
|
||||
"sha256": "10DA91C08E96E5FCA452E06E11029908A6F237356E4DB11AF1AD13FFA2E57A47"
|
||||
"path": "angle/bin/libGLESv2.dll",
|
||||
"sha256": "6DE6940EDB728396CBA6F3C0D79172A8EFD33E37671A13B1721C652EECEBF4C4"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_revision.h",
|
||||
"sha256": "C28DA498955466CEF76278184636A3297F103AE34D9B605394BA6FE1B75F1850"
|
||||
"path": "love/bin/love.dll",
|
||||
"sha256": "7B1BE4699AC950173474BB0C03B5DD52E1202ABA6F60C29E294957057F587692"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_render.h",
|
||||
"sha256": "A0CF0DB1A13D0DD0D8BFDC01FFB371E2B19BE36326F85058200AC9481876C7F0"
|
||||
"path": "love/bin/lua51.dll",
|
||||
"sha256": "08380FB9A7C8A8A85D3425C1FD6F1CB826D980FF31925453E353227E9A23BC70"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_rect.h",
|
||||
"sha256": "01DB368D4B7736E2358CD29EEC0D187D964CFD6182CFFAB57A938ADF73B6A418"
|
||||
"path": "love/lib/liblove.lib",
|
||||
"sha256": "C93A358D5EAE8BE3D74DDFDFA767657E96E95E0151F843FEB4E587CF2D89320A"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_quit.h",
|
||||
"sha256": "9C902ABAEA7560F98FC546BD35A04629A205D047DF5433FC30B0C1D81AF58B21"
|
||||
"path": "love/lib/lovestatic.lib",
|
||||
"sha256": "15FB3A9CB3C3CDAB8B33DE5B1D1F8D8FF6CE9719E9AA7BC2CF3D7B51CDCE0C98"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_power.h",
|
||||
"sha256": "FBBDF3FF13B21095623EDFC5659C1B76C6DBB1364A4DD14D8F9E5CF329048784"
|
||||
"path": "love/lib/lua51.lib",
|
||||
"sha256": "A4F4F0942A432B88A3541A185B3D3D5B4D58413B3CEEE10A2E48CAF9D8439759"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_platform.h",
|
||||
"sha256": "9CE62823791D7A16B9AD17AD11F4DE8DCBCDE7918F67BF6D1DD4FC625B69E50C"
|
||||
"path": "runtime/bin/brotlicommon.dll",
|
||||
"sha256": "6A1D267564FE5BE6D601C1F5301F45DD0D0CCBDA2AE8975CACA4424A9FD452AF"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_pixels.h",
|
||||
"sha256": "FEE61AEE337A3823E832F5C26B3000315D6EB95DA91BA20D4FB0B5BAC9D4967A"
|
||||
"path": "runtime/bin/brotlidec.dll",
|
||||
"sha256": "C12C983AEE4E7EF966982AD11D71B32456CB445B18B8E11D9A35E781619085E2"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_opengles2.h",
|
||||
"sha256": "73A3B042F7B3D296904BFF91268730D5180638F4EC1836D57258FE53EE60DF8B"
|
||||
"path": "runtime/bin/bz2.dll",
|
||||
"sha256": "28ADC0239EAF51D13F8C7075B8514420CAE92EFF14471EC6F5B56A11D9345F00"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_opengles2_khrplatform.h",
|
||||
"sha256": "7B1E01AAA7AD8F6FC34B5C7BDF79EBF5189BB09E2C4D2E79FC5D350623D11E83"
|
||||
"path": "runtime/bin/fmt.dll",
|
||||
"sha256": "B4ED319D0733EA619D11770558957AFBDF99021D86A4ED068628AE34426C6090"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_opengles2_gl2platform.h",
|
||||
"sha256": "4779BE999ACD1904458238F09C86983B7960AC40E612E05DB2DB97DB615F1E0F"
|
||||
"path": "runtime/bin/freetype.dll",
|
||||
"sha256": "3727B17849902FE12DED3C76BD71D2907C523CF67D1A7CB516025522E260F9D4"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_opengles2_gl2ext.h",
|
||||
"sha256": "4FC5B0034DCDE9C125922E3E70D01489A6B335076856EE660294E1A6305A3719"
|
||||
"path": "runtime/bin/libpng16.dll",
|
||||
"sha256": "9B3B823A59ABCB4BA43D1E6DB4C35855AE66384106E32FD5F9D486A7DECB81AF"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_opengles2_gl2.h",
|
||||
"sha256": "D6EC44B1D73F3AFCE3A20AC6976DB7FB3DAC656C5190F0B563E4CE90D79A15AA"
|
||||
"path": "runtime/bin/ogg.dll",
|
||||
"sha256": "283B0890599450AE4BE486C07241ECCC7B14B480465AF7F8D9F2A84528064A65"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_opengles.h",
|
||||
"sha256": "0542791816FCDD84B74D98347AC1B00A97BC6C2CDF31334CD9083789FFB6594A"
|
||||
"path": "runtime/bin/OpenAL32.dll",
|
||||
"sha256": "D37D04CDD1EEE2005ACF64B558DFB16F0A0D83991F3B2A75E5C69FF314054F8B"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_opengl.h",
|
||||
"sha256": "C4D2857E757B2B2A83D7531CBEDA19C383AD6D16648AB9B7544FC0A74EB2FF13"
|
||||
"path": "runtime/bin/theora.dll",
|
||||
"sha256": "C90101C9C169B68F4FA155E63C71F28B271BBB68649085C8ACEFB26816663857"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_opengl_glext.h",
|
||||
"sha256": "1ABB28891C9B0661B6FF3749DE2671DA5FE12BEB5BCB1833B2D6BDF5C89ECDF8"
|
||||
"path": "runtime/bin/theoradec.dll",
|
||||
"sha256": "53A5A3A0B24F72B7D8812DE4B78FD3BB222399B9293B577A8FCF80009B72F004"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_name.h",
|
||||
"sha256": "FDC6C648734220285056AD8B8273511C75D5BE00D17FC1EA3EB4C06526B13FA3"
|
||||
"path": "runtime/bin/vorbis.dll",
|
||||
"sha256": "A4B2D0A4C032A7E60AA297ADAE134E8A2C1BE61D7EC639CAA93AF85BF7EAC2C7"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_mutex.h",
|
||||
"sha256": "C5EF9A8AEB056422EF878672770E1F60AE965933693DF6D8EBD53D0E514A1794"
|
||||
"path": "runtime/bin/vorbisfile.dll",
|
||||
"sha256": "0BFFA35539F0A8233A8EFF4C6680F8A7CF3B9DBE3B437A3F94D5301B66A2F134"
|
||||
},
|
||||
{
|
||||
"path": "runtime/bin/z.dll",
|
||||
"sha256": "8B86502ADC15A13C0E136FB9D63AA6583C59AD93EC608A9A7C901757354744C3"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/bin/SDL2.dll",
|
||||
"sha256": "B02D13F77221A335AB9F21304F2B4E003FE59C6DF10F21BA6D49023016D35CA8"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/begin_code.h",
|
||||
"sha256": "9803DAB29FB4522CE3500AB789260E9622DF6307CE90F92AD20C1808E19C4E7B"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/close_code.h",
|
||||
"sha256": "4599E9CEDBA7451FF07A6306F0B7531BEED05B1C5A65B1A2613D1B771BE43FDA"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_assert.h",
|
||||
"sha256": "32FC342E0A5F3A55EA1CE2A5D9195E77215EDCB6F4595C0DC3674DCCA1CC81D8"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_atomic.h",
|
||||
"sha256": "C561CE8F94DE18CCB4F708BDA45880BA6D3C9F052E166BEB5DADC5544F35221E"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_audio.h",
|
||||
"sha256": "047AFC29591AC43A90F06169F67EE7D99A6256C6BBE5EFE5DE79A52565BB6853"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_bits.h",
|
||||
"sha256": "63D22D1C8FE0D83BBA5A49ABA9BB700592F14462F7F7BF87E5838064047E3FA9"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_blendmode.h",
|
||||
"sha256": "1985F81B886D9BC681821AF4F23D28E6E51BF51F21E5EF28CCC13BC8C7CDFBAE"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_clipboard.h",
|
||||
"sha256": "3E8C73FB9B3CA5A544B70B66B683B78DB53E1A187E066912A068C0ED7BB3E8CE"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_config.h",
|
||||
"sha256": "108A953419E1638AE2FF09148E2927C3AC4FF3E15B72A56FF41B542F356021BA"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_copying.h",
|
||||
"sha256": "3F90BE470C18F99F4AEF39444E9374EDBA166CFEB1B90F99F35286CC33924642"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_cpuinfo.h",
|
||||
"sha256": "FEE0C489ED4364C21FE0B726A47F72DF167FBCBF42CF569807B2BBF77DC30C54"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_egl.h",
|
||||
"sha256": "72C119F4F7EC30F13B03D3E33D2266CB012EE103F0AD1973786D84D538A0B53D"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_endian.h",
|
||||
"sha256": "7907CB3AB7B8D7BC99274F5AEF5294BEF215B01EA49D97226CBE6E911DE557D5"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_error.h",
|
||||
"sha256": "0931656A5825E5F1F319F2CD3F573FC527393BB02FA7A1ED3F7FAE6C790328BE"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_events.h",
|
||||
"sha256": "CEB7BC717342E652E2C432FD1DD08A5508575CEA6BD8615FB4DDEA63C071DDC4"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_filesystem.h",
|
||||
"sha256": "DCFAA010C73150E7B0D56F50F5ADB3FC2E35621091A55BC5436B2FB85FE71675"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_gamecontroller.h",
|
||||
"sha256": "C77C1D8287EE441843B9D8BE87B71252BDB1CE76B7BFC4FCFF46889AD8E9CFEC"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_gesture.h",
|
||||
"sha256": "A5A8F8BB8EFB26860FAA9694189AAF76DF1CDB7755CCD30A8599B46B237A5D82"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_guid.h",
|
||||
"sha256": "DA8FEF1D047B31E55D1B167DE301A806481B6948E7C2497779FD71934C45D5DB"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_haptic.h",
|
||||
"sha256": "4267B6F039BEA7AD0F5CB37C37D63D0704AF84F73A36D2680684FF302F49F153"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_hidapi.h",
|
||||
"sha256": "489A83D1073E528F82E821C23C515AF8B5A59357EC5AB132C854BB588648F59F"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_hints.h",
|
||||
"sha256": "96C1056E0734F019B1DAFED5129D4A9D36253559ED8C7577A23C188BB75A48C1"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_joystick.h",
|
||||
"sha256": "A39FC5DA97EDC94EABFF8616A413CF850EFB35D1DAF437A8CC16CAA837766482"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_keyboard.h",
|
||||
"sha256": "F68DFA4F784F0B22949A8DF94F3C3653EA01A03AE02297D17579EB9E7EA94054"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_keycode.h",
|
||||
"sha256": "291C769A05BC3E1EAD011DB3E07CB52415E1AA306F484904D203E94CBB3186CD"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_loadso.h",
|
||||
"sha256": "8D3653B7B774B406A289519C74AE695EB5B52D71060712A88FCE4C72D82B1BD3"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_locale.h",
|
||||
"sha256": "C4A663CE8EA4CA22F961796CAE644A04FC521FA2D0681333F7DA8A581909560C"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_log.h",
|
||||
"sha256": "3342CB31280C2DBF0E5809B03E5499F0CF5EDF193EFA5E3C5B17814526A92033"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_main.h",
|
||||
"sha256": "622FFCD0E7FE0C755A987C5EB9DAD6B3672774026B8250B66AD3C40D3A4DDA9A"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_messagebox.h",
|
||||
"sha256": "65DF549CAB0A515145AE55325C447159AE1D60171331A7508EAC06034D25C972"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_metal.h",
|
||||
"sha256": "1F3D0251522B735B0E37677EB1A0594440599FBBB2AF86BBB508606CCA001A06"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_misc.h",
|
||||
"sha256": "5D5E4B42481A5EF44EC9D66159E88426BE5632262731A3C3B223277771D30006"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_mouse.h",
|
||||
"sha256": "66B5353387D011A54B232931E86121CB5551E251B9491B9ED15AFE293D5856FF"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_misc.h",
|
||||
"sha256": "5D5E4B42481A5EF44EC9D66159E88426BE5632262731A3C3B223277771D30006"
|
||||
"path": "sdl2/include/SDL2/SDL_mutex.h",
|
||||
"sha256": "C5EF9A8AEB056422EF878672770E1F60AE965933693DF6D8EBD53D0E514A1794"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_name.h",
|
||||
"sha256": "FDC6C648734220285056AD8B8273511C75D5BE00D17FC1EA3EB4C06526B13FA3"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_opengl_glext.h",
|
||||
"sha256": "1ABB28891C9B0661B6FF3749DE2671DA5FE12BEB5BCB1833B2D6BDF5C89ECDF8"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_opengl.h",
|
||||
"sha256": "C4D2857E757B2B2A83D7531CBEDA19C383AD6D16648AB9B7544FC0A74EB2FF13"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_opengles.h",
|
||||
"sha256": "0542791816FCDD84B74D98347AC1B00A97BC6C2CDF31334CD9083789FFB6594A"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_opengles2_gl2.h",
|
||||
"sha256": "D6EC44B1D73F3AFCE3A20AC6976DB7FB3DAC656C5190F0B563E4CE90D79A15AA"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_opengles2_gl2ext.h",
|
||||
"sha256": "4FC5B0034DCDE9C125922E3E70D01489A6B335076856EE660294E1A6305A3719"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_opengles2_gl2platform.h",
|
||||
"sha256": "4779BE999ACD1904458238F09C86983B7960AC40E612E05DB2DB97DB615F1E0F"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_opengles2_khrplatform.h",
|
||||
"sha256": "7B1E01AAA7AD8F6FC34B5C7BDF79EBF5189BB09E2C4D2E79FC5D350623D11E83"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_opengles2.h",
|
||||
"sha256": "73A3B042F7B3D296904BFF91268730D5180638F4EC1836D57258FE53EE60DF8B"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_pixels.h",
|
||||
"sha256": "FEE61AEE337A3823E832F5C26B3000315D6EB95DA91BA20D4FB0B5BAC9D4967A"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_platform.h",
|
||||
"sha256": "9CE62823791D7A16B9AD17AD11F4DE8DCBCDE7918F67BF6D1DD4FC625B69E50C"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_power.h",
|
||||
"sha256": "FBBDF3FF13B21095623EDFC5659C1B76C6DBB1364A4DD14D8F9E5CF329048784"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_quit.h",
|
||||
"sha256": "9C902ABAEA7560F98FC546BD35A04629A205D047DF5433FC30B0C1D81AF58B21"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_rect.h",
|
||||
"sha256": "01DB368D4B7736E2358CD29EEC0D187D964CFD6182CFFAB57A938ADF73B6A418"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_render.h",
|
||||
"sha256": "A0CF0DB1A13D0DD0D8BFDC01FFB371E2B19BE36326F85058200AC9481876C7F0"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_revision.h",
|
||||
"sha256": "EF28EADA36B000C710B033317A37677B5484A4DE224547CB7293A77FA0C97195"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_rwops.h",
|
||||
"sha256": "10DA91C08E96E5FCA452E06E11029908A6F237356E4DB11AF1AD13FFA2E57A47"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_scancode.h",
|
||||
"sha256": "EB14F3CEDDE58358F6456D185F473D7551E8234DE260151AD0319861FF1444C2"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_sensor.h",
|
||||
@@ -190,305 +398,97 @@
|
||||
"sha256": "92299233370D645F78D9C655CE7F102C16F9D4DDDE28A59BD82A962C49B51D94"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_vulkan.h",
|
||||
"sha256": "98ED6B3D354191019AE208FC861799237BA8FFB11FA6BD41B3569E6CE05555B8"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_video.h",
|
||||
"sha256": "82AB63FF37834CD4BFCEE490B8E37FB892BBB0B31A1A7913EC13C329271CA5FF"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_version.h",
|
||||
"sha256": "EE97570D0D6507B4687076336C07FD4A7FA1F5E7986C9B61893A279950FEBCE8"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_types.h",
|
||||
"sha256": "ED0C92BED5EEC2648F744E8451F3AC5140C1EF11510175FA1B726273DBDED9ED"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_touch.h",
|
||||
"sha256": "4E5D7A083BBF5237DAF5CCF06FAED3FAE81B1CAA693E27841EBF4EC9BF8FF769"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_timer.h",
|
||||
"sha256": "D0497AD3D75701613A227134D63FDCBC62ED72F645153D52753E386EE4B498C7"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_thread.h",
|
||||
"sha256": "0E546047DD407CA0E1D2D686CF2650AC77A987047184E3645F6BA2EC958DDC5C"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_test.h",
|
||||
"sha256": "55E453735FB6A14CF350F663E8C7BC9AA273DB95BB31BCF3ABBFB5B3A91A414E"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_test_random.h",
|
||||
"sha256": "1D8C7987AE39B74D83F40FB54394FD32C61037716C77EBCAF7CE87788934C035"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_test_memory.h",
|
||||
"sha256": "556F676637FBB1A85F1998545C59ADDCA358B8B95C71812337B370184F27483F"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_metal.h",
|
||||
"sha256": "1F3D0251522B735B0E37677EB1A0594440599FBBB2AF86BBB508606CCA001A06"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_test_md5.h",
|
||||
"sha256": "BE73865B584B5EB207CAB3D8DCFF6AD057286B75053B547B0238DF275E282491"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_test_images.h",
|
||||
"sha256": "35E7AD856A201FBAAFE7EC3FC48DB47FB5D9452C292267F8936AEC5E5C77B81D"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_test_harness.h",
|
||||
"sha256": "30B9CCB36E07FF0442429A27540F6A796AEE073355B538BD50EF0B98CC47982E"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_test_fuzzer.h",
|
||||
"sha256": "494E0E49882A9C2745D07DA7B04761D8D992DD90A7A29DD34B605051ED8DCEE5"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_test_font.h",
|
||||
"sha256": "B0B7E6AC8BCF7B9E5BF28695B05D3A084CD530C90322CBC9A0B198114B174231"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_test_crc32.h",
|
||||
"sha256": "74CB4C2F7F7130D6048A2C716260D6403620F0E358FA928136ED3560BF71A378"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_test_compare.h",
|
||||
"sha256": "713AF284D8520E910D94090396BFD2DB2B2292096EDD93E4D60AA69163B9C510"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_test_common.h",
|
||||
"sha256": "B619CC3020FFDC8F8A12F5D9D4AF8B83E9B7C6C3BFC05C6502933C4B3F0103DE"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_test_assert.h",
|
||||
"sha256": "FE826FEB054929284764718C67AE95B920729AE1336FFEEC88A23D611E6498F0"
|
||||
"path": "sdl2/include/SDL2/SDL_system.h",
|
||||
"sha256": "FFC5F3662A85F795C0B2E2B87B9FBF493BCEEDA4AACF7721A68225C5E318CA67"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_syswm.h",
|
||||
"sha256": "34FEC1A5F1089BD395EE11C3A25AD0FC10E7ABC56D4A77CC6F17EB9E4E8A9607"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_system.h",
|
||||
"sha256": "FFC5F3662A85F795C0B2E2B87B9FBF493BCEEDA4AACF7721A68225C5E318CA67"
|
||||
"path": "sdl2/include/SDL2/SDL_test_assert.h",
|
||||
"sha256": "FE826FEB054929284764718C67AE95B920729AE1336FFEEC88A23D611E6498F0"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_test_common.h",
|
||||
"sha256": "B619CC3020FFDC8F8A12F5D9D4AF8B83E9B7C6C3BFC05C6502933C4B3F0103DE"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_test_compare.h",
|
||||
"sha256": "713AF284D8520E910D94090396BFD2DB2B2292096EDD93E4D60AA69163B9C510"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_test_crc32.h",
|
||||
"sha256": "74CB4C2F7F7130D6048A2C716260D6403620F0E358FA928136ED3560BF71A378"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_test_font.h",
|
||||
"sha256": "B0B7E6AC8BCF7B9E5BF28695B05D3A084CD530C90322CBC9A0B198114B174231"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_test_fuzzer.h",
|
||||
"sha256": "494E0E49882A9C2745D07DA7B04761D8D992DD90A7A29DD34B605051ED8DCEE5"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_test_harness.h",
|
||||
"sha256": "30B9CCB36E07FF0442429A27540F6A796AEE073355B538BD50EF0B98CC47982E"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_test_images.h",
|
||||
"sha256": "35E7AD856A201FBAAFE7EC3FC48DB47FB5D9452C292267F8936AEC5E5C77B81D"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_test_log.h",
|
||||
"sha256": "3A8736E6D757666420616F83E7929493FCBE816A0CDDF10347F3446818870BE8"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_messagebox.h",
|
||||
"sha256": "65DF549CAB0A515145AE55325C447159AE1D60171331A7508EAC06034D25C972"
|
||||
"path": "sdl2/include/SDL2/SDL_test_md5.h",
|
||||
"sha256": "BE73865B584B5EB207CAB3D8DCFF6AD057286B75053B547B0238DF275E282491"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_main.h",
|
||||
"sha256": "622FFCD0E7FE0C755A987C5EB9DAD6B3672774026B8250B66AD3C40D3A4DDA9A"
|
||||
"path": "sdl2/include/SDL2/SDL_test_memory.h",
|
||||
"sha256": "556F676637FBB1A85F1998545C59ADDCA358B8B95C71812337B370184F27483F"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_log.h",
|
||||
"sha256": "3342CB31280C2DBF0E5809B03E5499F0CF5EDF193EFA5E3C5B17814526A92033"
|
||||
"path": "sdl2/include/SDL2/SDL_test_random.h",
|
||||
"sha256": "1D8C7987AE39B74D83F40FB54394FD32C61037716C77EBCAF7CE87788934C035"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/begin_code.h",
|
||||
"sha256": "9803DAB29FB4522CE3500AB789260E9622DF6307CE90F92AD20C1808E19C4E7B"
|
||||
"path": "sdl2/include/SDL2/SDL_test.h",
|
||||
"sha256": "55E453735FB6A14CF350F663E8C7BC9AA273DB95BB31BCF3ABBFB5B3A91A414E"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/bin/SDL2.dll",
|
||||
"sha256": "B02D13F77221A335AB9F21304F2B4E003FE59C6DF10F21BA6D49023016D35CA8"
|
||||
"path": "sdl2/include/SDL2/SDL_thread.h",
|
||||
"sha256": "0E546047DD407CA0E1D2D686CF2650AC77A987047184E3645F6BA2EC958DDC5C"
|
||||
},
|
||||
{
|
||||
"path": "runtime/bin/z.dll",
|
||||
"sha256": "8B86502ADC15A13C0E136FB9D63AA6583C59AD93EC608A9A7C901757354744C3"
|
||||
"path": "sdl2/include/SDL2/SDL_timer.h",
|
||||
"sha256": "D0497AD3D75701613A227134D63FDCBC62ED72F645153D52753E386EE4B498C7"
|
||||
},
|
||||
{
|
||||
"path": "runtime/bin/vorbisfile.dll",
|
||||
"sha256": "0BFFA35539F0A8233A8EFF4C6680F8A7CF3B9DBE3B437A3F94D5301B66A2F134"
|
||||
"path": "sdl2/include/SDL2/SDL_touch.h",
|
||||
"sha256": "4E5D7A083BBF5237DAF5CCF06FAED3FAE81B1CAA693E27841EBF4EC9BF8FF769"
|
||||
},
|
||||
{
|
||||
"path": "runtime/bin/vorbis.dll",
|
||||
"sha256": "A4B2D0A4C032A7E60AA297ADAE134E8A2C1BE61D7EC639CAA93AF85BF7EAC2C7"
|
||||
"path": "sdl2/include/SDL2/SDL_types.h",
|
||||
"sha256": "ED0C92BED5EEC2648F744E8451F3AC5140C1EF11510175FA1B726273DBDED9ED"
|
||||
},
|
||||
{
|
||||
"path": "runtime/bin/theoradec.dll",
|
||||
"sha256": "53A5A3A0B24F72B7D8812DE4B78FD3BB222399B9293B577A8FCF80009B72F004"
|
||||
"path": "sdl2/include/SDL2/SDL_version.h",
|
||||
"sha256": "EE97570D0D6507B4687076336C07FD4A7FA1F5E7986C9B61893A279950FEBCE8"
|
||||
},
|
||||
{
|
||||
"path": "runtime/bin/theora.dll",
|
||||
"sha256": "C90101C9C169B68F4FA155E63C71F28B271BBB68649085C8ACEFB26816663857"
|
||||
"path": "sdl2/include/SDL2/SDL_video.h",
|
||||
"sha256": "82AB63FF37834CD4BFCEE490B8E37FB892BBB0B31A1A7913EC13C329271CA5FF"
|
||||
},
|
||||
{
|
||||
"path": "runtime/bin/OpenAL32.dll",
|
||||
"sha256": "D37D04CDD1EEE2005ACF64B558DFB16F0A0D83991F3B2A75E5C69FF314054F8B"
|
||||
},
|
||||
{
|
||||
"path": "runtime/bin/ogg.dll",
|
||||
"sha256": "283B0890599450AE4BE486C07241ECCC7B14B480465AF7F8D9F2A84528064A65"
|
||||
},
|
||||
{
|
||||
"path": "runtime/bin/libpng16.dll",
|
||||
"sha256": "9B3B823A59ABCB4BA43D1E6DB4C35855AE66384106E32FD5F9D486A7DECB81AF"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/close_code.h",
|
||||
"sha256": "4599E9CEDBA7451FF07A6306F0B7531BEED05B1C5A65B1A2613D1B771BE43FDA"
|
||||
},
|
||||
{
|
||||
"path": "runtime/bin/freetype.dll",
|
||||
"sha256": "3727B17849902FE12DED3C76BD71D2907C523CF67D1A7CB516025522E260F9D4"
|
||||
},
|
||||
{
|
||||
"path": "runtime/bin/bz2.dll",
|
||||
"sha256": "28ADC0239EAF51D13F8C7075B8514420CAE92EFF14471EC6F5B56A11D9345F00"
|
||||
},
|
||||
{
|
||||
"path": "runtime/bin/brotlidec.dll",
|
||||
"sha256": "C12C983AEE4E7EF966982AD11D71B32456CB445B18B8E11D9A35E781619085E2"
|
||||
},
|
||||
{
|
||||
"path": "runtime/bin/brotlicommon.dll",
|
||||
"sha256": "6A1D267564FE5BE6D601C1F5301F45DD0D0CCBDA2AE8975CACA4424A9FD452AF"
|
||||
},
|
||||
{
|
||||
"path": "love/lib/lua51.lib",
|
||||
"sha256": "A4F4F0942A432B88A3541A185B3D3D5B4D58413B3CEEE10A2E48CAF9D8439759"
|
||||
},
|
||||
{
|
||||
"path": "love/lib/lovestatic.lib",
|
||||
"sha256": "15FB3A9CB3C3CDAB8B33DE5B1D1F8D8FF6CE9719E9AA7BC2CF3D7B51CDCE0C98"
|
||||
},
|
||||
{
|
||||
"path": "love/lib/liblove.lib",
|
||||
"sha256": "C93A358D5EAE8BE3D74DDFDFA767657E96E95E0151F843FEB4E587CF2D89320A"
|
||||
},
|
||||
{
|
||||
"path": "love/bin/lua51.dll",
|
||||
"sha256": "08380FB9A7C8A8A85D3425C1FD6F1CB826D980FF31925453E353227E9A23BC70"
|
||||
},
|
||||
{
|
||||
"path": "love/bin/love.dll",
|
||||
"sha256": "7B1BE4699AC950173474BB0C03B5DD52E1202ABA6F60C29E294957057F587692"
|
||||
},
|
||||
{
|
||||
"path": "angle/bin/libGLESv2.dll",
|
||||
"sha256": "6DE6940EDB728396CBA6F3C0D79172A8EFD33E37671A13B1721C652EECEBF4C4"
|
||||
},
|
||||
{
|
||||
"path": "angle/bin/libEGL.dll",
|
||||
"sha256": "B0E0C6BAC9D9F0F084DC8F56083A2EEFFB866C0629A64D52B5E33616B4F90CBE"
|
||||
},
|
||||
{
|
||||
"path": "runtime/bin/fmt.dll",
|
||||
"sha256": "B4ED319D0733EA619D11770558957AFBDF99021D86A4ED068628AE34426C6090"
|
||||
"path": "sdl2/include/SDL2/SDL_vulkan.h",
|
||||
"sha256": "98ED6B3D354191019AE208FC861799237BA8FFB11FA6BD41B3569E6CE05555B8"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL.h",
|
||||
"sha256": "952E89E1DC4E0DD1A7BEA6A153DF632B8CDB6E433A9B3B0702C5FFE15B9B9360"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_assert.h",
|
||||
"sha256": "32FC342E0A5F3A55EA1CE2A5D9195E77215EDCB6F4595C0DC3674DCCA1CC81D8"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_audio.h",
|
||||
"sha256": "047AFC29591AC43A90F06169F67EE7D99A6256C6BBE5EFE5DE79A52565BB6853"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_locale.h",
|
||||
"sha256": "C4A663CE8EA4CA22F961796CAE644A04FC521FA2D0681333F7DA8A581909560C"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_loadso.h",
|
||||
"sha256": "8D3653B7B774B406A289519C74AE695EB5B52D71060712A88FCE4C72D82B1BD3"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_keycode.h",
|
||||
"sha256": "291C769A05BC3E1EAD011DB3E07CB52415E1AA306F484904D203E94CBB3186CD"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_keyboard.h",
|
||||
"sha256": "F68DFA4F784F0B22949A8DF94F3C3653EA01A03AE02297D17579EB9E7EA94054"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_joystick.h",
|
||||
"sha256": "A39FC5DA97EDC94EABFF8616A413CF850EFB35D1DAF437A8CC16CAA837766482"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_hints.h",
|
||||
"sha256": "96C1056E0734F019B1DAFED5129D4A9D36253559ED8C7577A23C188BB75A48C1"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_hidapi.h",
|
||||
"sha256": "489A83D1073E528F82E821C23C515AF8B5A59357EC5AB132C854BB588648F59F"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_haptic.h",
|
||||
"sha256": "4267B6F039BEA7AD0F5CB37C37D63D0704AF84F73A36D2680684FF302F49F153"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_guid.h",
|
||||
"sha256": "DA8FEF1D047B31E55D1B167DE301A806481B6948E7C2497779FD71934C45D5DB"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_gesture.h",
|
||||
"sha256": "A5A8F8BB8EFB26860FAA9694189AAF76DF1CDB7755CCD30A8599B46B237A5D82"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_atomic.h",
|
||||
"sha256": "C561CE8F94DE18CCB4F708BDA45880BA6D3C9F052E166BEB5DADC5544F35221E"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_gamecontroller.h",
|
||||
"sha256": "C77C1D8287EE441843B9D8BE87B71252BDB1CE76B7BFC4FCFF46889AD8E9CFEC"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_events.h",
|
||||
"sha256": "CEB7BC717342E652E2C432FD1DD08A5508575CEA6BD8615FB4DDEA63C071DDC4"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_error.h",
|
||||
"sha256": "0931656A5825E5F1F319F2CD3F573FC527393BB02FA7A1ED3F7FAE6C790328BE"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_endian.h",
|
||||
"sha256": "7907CB3AB7B8D7BC99274F5AEF5294BEF215B01EA49D97226CBE6E911DE557D5"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_egl.h",
|
||||
"sha256": "72C119F4F7EC30F13B03D3E33D2266CB012EE103F0AD1973786D84D538A0B53D"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_cpuinfo.h",
|
||||
"sha256": "FEE0C489ED4364C21FE0B726A47F72DF167FBCBF42CF569807B2BBF77DC30C54"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_copying.h",
|
||||
"sha256": "3F90BE470C18F99F4AEF39444E9374EDBA166CFEB1B90F99F35286CC33924642"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_config.h",
|
||||
"sha256": "1B33FCD93DEFBC0B0C396FB5BC98DE5CAD0868A347417167C0D8CA2C68A823DA"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_clipboard.h",
|
||||
"sha256": "3E8C73FB9B3CA5A544B70B66B683B78DB53E1A187E066912A068C0ED7BB3E8CE"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_blendmode.h",
|
||||
"sha256": "1985F81B886D9BC681821AF4F23D28E6E51BF51F21E5EF28CCC13BC8C7CDFBAE"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_bits.h",
|
||||
"sha256": "63D22D1C8FE0D83BBA5A49ABA9BB700592F14462F7F7BF87E5838064047E3FA9"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/include/SDL2/SDL_filesystem.h",
|
||||
"sha256": "DCFAA010C73150E7B0D56F50F5ADB3FC2E35621091A55BC5436B2FB85FE71675"
|
||||
},
|
||||
{
|
||||
"path": "sdl2/lib/SDL2.lib",
|
||||
"sha256": "37B330EE42407B405BD2432E79CB9B9036245309B3ACC445AD70CB8E555B7288"
|
||||
|
||||
Vendored
+1
-1
@@ -6,4 +6,4 @@ The bundled x64 UWP Release binaries use SDL 2.32.10 from the official `release-
|
||||
|
||||
`SDL2.dll`, `SDL2.lib`, and the headers must be updated together.
|
||||
|
||||
`ports/uwp/scripts/build-sdl2-angle.ps1` builds the source for x64 WindowsStore with GLES enabled and desktop OpenGL and Vulkan disabled. ANGLE supplies EGL and GLES at runtime.
|
||||
`scripts/xbox-uwp/build_sdl2_angle.ps1` builds the source for x64 WindowsStore with GLES enabled and desktop OpenGL and Vulkan disabled. ANGLE supplies EGL and GLES at runtime.
|
||||
|
||||
@@ -1,28 +1,19 @@
|
||||
diff --git a/src/joystick/SDL_gamecontroller.c b/src/joystick/SDL_gamecontroller.c
|
||||
index 035176b..04e1701 100644
|
||||
index 36e521e..4d1f171 100644
|
||||
--- a/src/joystick/SDL_gamecontroller.c
|
||||
+++ b/src/joystick/SDL_gamecontroller.c
|
||||
@@ -726,7 +726,12 @@ static ControllerMapping_t *SDL_CreateMappingForWGIController(SDL_JoystickGUID g
|
||||
}
|
||||
|
||||
SDL_strlcpy(mapping_string, "none,*,", sizeof(mapping_string));
|
||||
@@ -682,0 +683,4 @@ static ControllerMapping_t *SDL_CreateMappingForWGIController(SDL_JoystickGUID g
|
||||
+#ifdef __WINRT__
|
||||
+ /* Xbox WGI exposes the canonical SDL axis and hat layout. */
|
||||
+ SDL_strlcat(mapping_string, "a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,leftstick:b8,rightstick:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,lefttrigger:a2,rightx:a3,righty:a4,righttrigger:a5,", sizeof(mapping_string));
|
||||
+#else
|
||||
SDL_strlcat(mapping_string, "a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,leftstick:b8,rightstick:b9,leftshoulder:b4,rightshoulder:b5,dpup:b10,dpdown:b12,dpleft:b13,dpright:b11,leftx:a1,lefty:a0~,rightx:a3,righty:a2~,lefttrigger:a4,righttrigger:a5,", sizeof(mapping_string));
|
||||
@@ -683,0 +688 @@ static ControllerMapping_t *SDL_CreateMappingForWGIController(SDL_JoystickGUID g
|
||||
+#endif
|
||||
|
||||
return SDL_PrivateAddMappingForGUID(guid, mapping_string, &existing, SDL_CONTROLLER_MAPPING_PRIORITY_DEFAULT);
|
||||
}
|
||||
diff --git a/src/joystick/windows/SDL_windows_gaming_input.c b/src/joystick/windows/SDL_windows_gaming_input.c
|
||||
index 6f01b4e..26b8811 100644
|
||||
index 9299ac5..9fce0a5 100644
|
||||
--- a/src/joystick/windows/SDL_windows_gaming_input.c
|
||||
+++ b/src/joystick/windows/SDL_windows_gaming_input.c
|
||||
@@ -731,10 +731,19 @@ static int WGI_JoystickOpen(SDL_Joystick *joystick, int device_index)
|
||||
__x_ABI_CWindows_CGaming_CInput_CIGameController_get_IsWireless(hwdata->gamecontroller, &wireless);
|
||||
}
|
||||
|
||||
@@ -793,4 +793,13 @@ static int WGI_JoystickOpen(SDL_Joystick *joystick, int device_index)
|
||||
- /* Initialize the joystick capabilities */
|
||||
- joystick->nbuttons = state->nbuttons;
|
||||
- joystick->naxes = state->naxes;
|
||||
@@ -40,13 +31,7 @@ index 6f01b4e..26b8811 100644
|
||||
+ joystick->naxes = state->naxes;
|
||||
+ joystick->nhats = state->nhats;
|
||||
+ }
|
||||
joystick->epowerlevel = wireless ? SDL_JOYSTICK_POWER_UNKNOWN : SDL_JOYSTICK_POWER_WIRED;
|
||||
|
||||
if (wireless && hwdata->battery) {
|
||||
@@ -872,6 +881,51 @@ static void WGI_JoystickUpdate(SDL_Joystick *joystick)
|
||||
{
|
||||
struct joystick_hwdata *hwdata = joystick->hwdata;
|
||||
HRESULT hr;
|
||||
@@ -933,0 +943,45 @@ static void WGI_JoystickUpdate(SDL_Joystick *joystick)
|
||||
+
|
||||
+#ifdef __WINRT__
|
||||
+ if (hwdata->gamepad) {
|
||||
@@ -92,13 +77,7 @@ index 6f01b4e..26b8811 100644
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
UINT32 nbuttons = SDL_min(joystick->nbuttons, SDL_MAX_UINT8);
|
||||
boolean *buttons = NULL;
|
||||
UINT32 nhats = SDL_min(joystick->nhats, SDL_MAX_UINT8);
|
||||
@@ -994,7 +1048,38 @@ static void WGI_JoystickQuit(void)
|
||||
|
||||
static SDL_bool WGI_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
|
||||
{
|
||||
@@ -1055,0 +1110,30 @@ static SDL_bool WGI_JoystickGetGamepadMapping(int device_index, SDL_GamepadMappi
|
||||
+#ifdef __WINRT__
|
||||
+ WindowsGamingInputControllerState *state = &wgi.controllers[device_index];
|
||||
+
|
||||
@@ -129,8 +108,5 @@ index 6f01b4e..26b8811 100644
|
||||
+ out->righttrigger = (SDL_InputMapping){ EMappingKind_Axis, 5 };
|
||||
+ return SDL_TRUE;
|
||||
+#else
|
||||
return SDL_FALSE;
|
||||
@@ -1056,0 +1141 @@ static SDL_bool WGI_JoystickGetGamepadMapping(int device_index, SDL_GamepadMappi
|
||||
+#endif
|
||||
}
|
||||
|
||||
SDL_JoystickDriver SDL_WGI_JoystickDriver = {
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
#!/usr/bin/env bash
|
||||
# Build the Xbox Dev Mode UWP package with the shared game.love payload.
|
||||
#
|
||||
# Usage:
|
||||
# scripts/build_xbox_uwp.sh [--release|--relwithdebinfo]
|
||||
# [--version X.Y.Z] [--game-love PATH]
|
||||
# [--publisher SUBJECT]
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=xbox-uwp/common.sh
|
||||
. "$SCRIPT_DIR/xbox-uwp/common.sh"
|
||||
|
||||
CONFIGURATION="Release"
|
||||
PRESET="uwp-release"
|
||||
GAME_LOVE=""
|
||||
VERSION="0.0.0"
|
||||
VERSION_EXPLICIT=0
|
||||
PUBLISHER="${GEN1RECOMP_UWP_PUBLISHER:-CN=Gen1Recomp}"
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--release)
|
||||
CONFIGURATION="Release"
|
||||
PRESET="uwp-release"
|
||||
shift
|
||||
;;
|
||||
--relwithdebinfo)
|
||||
CONFIGURATION="RelWithDebInfo"
|
||||
PRESET="uwp-relwithdebinfo"
|
||||
shift
|
||||
;;
|
||||
--game-love)
|
||||
[ $# -ge 2 ] || fail "--game-love requires a path"
|
||||
GAME_LOVE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--version)
|
||||
[ $# -ge 2 ] || fail "--version requires X.Y.Z"
|
||||
VERSION="$2"
|
||||
VERSION_EXPLICIT=1
|
||||
shift 2
|
||||
;;
|
||||
--publisher)
|
||||
[ $# -ge 2 ] || fail "--publisher requires a certificate subject"
|
||||
PUBLISHER="$2"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
sed -n '2,7p' "$0" | sed 's/^# \{0,1\}//'
|
||||
exit 0
|
||||
;;
|
||||
*) fail "unknown argument: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
case "$(uname -s)" in
|
||||
MINGW*|MSYS*|CYGWIN*) ;;
|
||||
*) fail "Xbox UWP packages must be built from Git Bash on Windows" ;;
|
||||
esac
|
||||
|
||||
require_command cmake
|
||||
require_command cygpath
|
||||
require_command powershell.exe
|
||||
require_command unzip
|
||||
printf '%s' "$VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$' \
|
||||
|| fail "invalid version '$VERSION' (expected X.Y.Z)"
|
||||
|
||||
if [ -z "$GAME_LOVE" ]; then
|
||||
require_command zip
|
||||
mkdir -p "$WORK"
|
||||
GAME_LOVE="$WORK/game.love"
|
||||
pack_args=(
|
||||
--output "$GAME_LOVE" \
|
||||
--listing "$WORK/love-listing.txt"
|
||||
)
|
||||
if [ "$VERSION_EXPLICIT" -eq 1 ]; then
|
||||
pack_args+=(--version "$VERSION")
|
||||
fi
|
||||
"$ROOT/scripts/pack_love.sh" "${pack_args[@]}"
|
||||
else
|
||||
GAME_LOVE="$(cd "$(dirname "$GAME_LOVE")" && pwd)/$(basename "$GAME_LOVE")"
|
||||
[ -f "$GAME_LOVE" ] || fail "missing game.love: $GAME_LOVE"
|
||||
"$ROOT/scripts/switch/verify_payload.sh" "$GAME_LOVE"
|
||||
if [ "$VERSION_EXPLICIT" -eq 1 ]; then
|
||||
version_re="$(printf '%s' "$VERSION" | sed 's/\./\\./g')"
|
||||
unzip -p "$GAME_LOVE" src/core/Version.lua \
|
||||
| grep -Eq "engine[[:space:]]*=[[:space:]]*\"$version_re\"" \
|
||||
|| fail "game.love does not report engine $VERSION"
|
||||
fi
|
||||
fi
|
||||
|
||||
say "configuring Xbox UWP ($CONFIGURATION)"
|
||||
cmake --preset "$PRESET" -S "$(windows_path "$UWP_ROOT")" \
|
||||
"-DGEN1RECOMP_LOVE:FILEPATH=$(windows_path "$GAME_LOVE")" \
|
||||
"-DGEN1RECOMP_VERSION:STRING=$VERSION" \
|
||||
"-DGEN1RECOMP_UWP_PUBLISHER:STRING=$PUBLISHER"
|
||||
|
||||
say "building Xbox UWP ($CONFIGURATION)"
|
||||
(cd "$UWP_ROOT" && cmake --build --preset "$PRESET")
|
||||
|
||||
build_info="$WORK/xbox-uwp-build-info.json"
|
||||
bash "$SCRIPT_DIR/xbox-uwp/write_build_info.sh" \
|
||||
"$build_info" "$VERSION" "$CONFIGURATION"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File \
|
||||
"$(windows_path "$SCRIPT_DIR/xbox-uwp/stage_release.ps1")" \
|
||||
-Version "$VERSION" \
|
||||
-Configuration "$CONFIGURATION" \
|
||||
-BuildInfo "$(windows_path "$build_info")"
|
||||
|
||||
say "done. See dist/xbox-uwp/"
|
||||
+22
-2
@@ -1,14 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
# Shared game.love packer for desktop and Switch builds.
|
||||
# Shared game.love packer for platform builds.
|
||||
#
|
||||
# Usage:
|
||||
# scripts/pack_love.sh [--output PATH] [--listing PATH] [--dry-run]
|
||||
# [--build-info PATH]
|
||||
# [--build-info PATH] [--version X.Y.Z]
|
||||
#
|
||||
# Packs the same include/exclude set as the desktop release. Materializes a
|
||||
# listing file once and greps it (avoids SIGPIPE from unzip|grep under pipefail).
|
||||
#
|
||||
# --build-info PATH copy JSON into the love archive root before verification
|
||||
# --version X.Y.Z stamp the release version inside the archive
|
||||
# --dry-run pack + verify only (for CI gates; no platform artifacts)
|
||||
|
||||
set -euo pipefail
|
||||
@@ -19,6 +20,7 @@ OUTPUT="$WORK/game.love"
|
||||
LISTING="$WORK/love-listing.txt"
|
||||
DRY_RUN=0
|
||||
BUILD_INFO=""
|
||||
VERSION=""
|
||||
|
||||
say() { printf '\033[1;32m==>\033[0m %s\n' "$*"; }
|
||||
fail() { printf '\033[1;31merror:\033[0m %s\n' "$*" >&2; exit 1; }
|
||||
@@ -28,6 +30,7 @@ while [ $# -gt 0 ]; do
|
||||
--output) OUTPUT="$2"; shift 2 ;;
|
||||
--listing) LISTING="$2"; shift 2 ;;
|
||||
--build-info) BUILD_INFO="$2"; shift 2 ;;
|
||||
--version) VERSION="$2"; shift 2 ;;
|
||||
--dry-run) DRY_RUN=1; shift ;;
|
||||
-h|--help)
|
||||
sed -n '2,12p' "$0" | sed 's/^# \{0,1\}//'
|
||||
@@ -56,6 +59,23 @@ if [ -n "$BUILD_INFO" ]; then
|
||||
(cd "$(dirname "$BUILD_INFO")" && zip -q "$OUTPUT" build-info.json)
|
||||
fi
|
||||
|
||||
if [ -n "$VERSION" ]; then
|
||||
printf '%s' "$VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$' \
|
||||
|| fail "invalid version '$VERSION' (expected X.Y.Z)"
|
||||
stamp_dir="$(mktemp -d "$WORK/stamp-love.XXXXXX")"
|
||||
output_abs="$(cd "$(dirname "$OUTPUT")" && pwd)/$(basename "$OUTPUT")"
|
||||
trap 'rm -rf "$stamp_dir"' EXIT
|
||||
mkdir -p "$stamp_dir/src/core"
|
||||
sed -E "s/(engine[[:space:]]*=[[:space:]]*\")[^\"]*(\")/\1$VERSION\2/" \
|
||||
"$ROOT/src/core/Version.lua" > "$stamp_dir/src/core/Version.lua"
|
||||
(cd "$stamp_dir" && zip -q "$output_abs" src/core/Version.lua)
|
||||
version_re="$(printf '%s' "$VERSION" | sed 's/\./\\./g')"
|
||||
unzip -p "$output_abs" src/core/Version.lua \
|
||||
| grep -Eq "engine[[:space:]]*=[[:space:]]*\"$version_re\"" \
|
||||
|| fail "version stamp failed: game.love does not report engine $VERSION"
|
||||
say "stamped engine version: $VERSION"
|
||||
fi
|
||||
|
||||
# Materialize the listing once. Piping unzip→grep -q under `set -o pipefail`
|
||||
# SIGPIPEs unzip when grep exits early on a match and aborts the build.
|
||||
unzip -Z1 "$OUTPUT" > "$LISTING"
|
||||
|
||||
@@ -5,7 +5,8 @@ param(
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$portRoot = Split-Path -Parent $PSScriptRoot
|
||||
$repoRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
|
||||
$portRoot = Join-Path $repoRoot "ports\uwp"
|
||||
$sourceRoot = Join-Path $portRoot "third_party\sdl2\source"
|
||||
$buildRoot = Join-Path $portRoot "build\sdl2"
|
||||
$installRoot = Join-Path $portRoot "build\sdl2-install"
|
||||
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
UWP_ROOT="$ROOT/ports/uwp"
|
||||
WORK="$ROOT/.bazinga/work"
|
||||
|
||||
say() { printf '\033[1;32m==>\033[0m %s\n' "$*"; }
|
||||
fail() { printf '\033[1;31merror:\033[0m %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
require_command() {
|
||||
command -v "$1" >/dev/null 2>&1 || fail "required command not found: $1"
|
||||
}
|
||||
|
||||
sha256_file() {
|
||||
local path="$1"
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
sha256sum "$path" | awk '{print $1}'
|
||||
elif command -v shasum >/dev/null 2>&1; then
|
||||
shasum -a 256 "$path" | awk '{print $1}'
|
||||
else
|
||||
fail "sha256sum or shasum is required"
|
||||
fi
|
||||
}
|
||||
|
||||
windows_path() {
|
||||
cygpath -aw "$1"
|
||||
}
|
||||
+79
-32
@@ -10,7 +10,8 @@ param(
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$portRoot = Split-Path -Parent $PSScriptRoot
|
||||
$repoRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
|
||||
$portRoot = Join-Path $repoRoot "ports\uwp"
|
||||
$thirdPartyRoot = Join-Path $portRoot "third_party"
|
||||
$manifestPath = Join-Path $thirdPartyRoot "manifest.json"
|
||||
$metadata = Get-Content -Raw -LiteralPath $manifestPath | ConvertFrom-Json
|
||||
@@ -61,7 +62,7 @@ function Ensure-GitSource {
|
||||
[Parameter(Mandatory)][string]$Repository,
|
||||
[Parameter(Mandatory)][string]$Revision,
|
||||
[Parameter(Mandatory)][string]$Path,
|
||||
[string]$SnapshotRevision
|
||||
[switch]$AllowTrackedChanges
|
||||
)
|
||||
|
||||
if (-not (Test-Path -LiteralPath $Path -PathType Container)) {
|
||||
@@ -74,28 +75,34 @@ function Ensure-GitSource {
|
||||
}
|
||||
|
||||
$gitDirectory = Join-Path $Path ".git"
|
||||
if (Test-Path -LiteralPath $gitDirectory) {
|
||||
$actual = (& git -C $Path rev-parse HEAD).Trim()
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Unable to inspect the $Name source checkout."
|
||||
}
|
||||
if ($actual -ne $Revision) {
|
||||
throw "$Name source is at $actual; expected $Revision. Remove '$Path' to recreate it."
|
||||
}
|
||||
return
|
||||
if (-not (Test-Path -LiteralPath $gitDirectory -PathType Container)) {
|
||||
throw "$Name source has no Git metadata. Remove '$Path' to recreate the pinned checkout."
|
||||
}
|
||||
|
||||
if (-not $SnapshotRevision) {
|
||||
throw "$Name source exists without Git metadata, so its revision cannot be verified."
|
||||
$actual = (& git -C $Path rev-parse HEAD).Trim()
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Unable to inspect the $Name source checkout."
|
||||
}
|
||||
if ($actual -ne $Revision) {
|
||||
throw "$Name source is at $actual; expected $Revision. Remove '$Path' to recreate it."
|
||||
}
|
||||
if (-not $AllowTrackedChanges) {
|
||||
Assert-GitSourceClean -Name $Name -Path $Path
|
||||
}
|
||||
}
|
||||
|
||||
$revisionFile = Join-Path $Path "REVISION.txt"
|
||||
if (-not (Test-Path -LiteralPath $revisionFile -PathType Leaf)) {
|
||||
throw "$Name source snapshot is missing REVISION.txt."
|
||||
}
|
||||
$actualSnapshot = (Get-Content -Raw -LiteralPath $revisionFile).Trim()
|
||||
if ($actualSnapshot -ne $SnapshotRevision) {
|
||||
throw "$Name source snapshot is '$actualSnapshot'; expected '$SnapshotRevision'."
|
||||
function Assert-GitSourceClean {
|
||||
param(
|
||||
[Parameter(Mandatory)][string]$Name,
|
||||
[Parameter(Mandatory)][string]$Path
|
||||
)
|
||||
|
||||
& git -C $Path diff --quiet --ignore-submodules --
|
||||
$worktreeDirty = $LASTEXITCODE -ne 0
|
||||
& git -C $Path diff --cached --quiet --ignore-submodules --
|
||||
$indexDirty = $LASTEXITCODE -ne 0
|
||||
if ($worktreeDirty -or $indexDirty) {
|
||||
throw "$Name source has local changes. Remove '$Path' to recreate the pinned checkout."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +140,22 @@ function Ensure-DepotToolsGit {
|
||||
}
|
||||
|
||||
function Get-Sha256 {
|
||||
param([Parameter(Mandatory)][string]$Path)
|
||||
param(
|
||||
[Parameter(Mandatory)][string]$Path,
|
||||
[switch]$NormalizeLineEndings
|
||||
)
|
||||
|
||||
if ($NormalizeLineEndings) {
|
||||
$bytes = [System.IO.File]::ReadAllBytes($Path)
|
||||
$text = [System.Text.Encoding]::UTF8.GetString($bytes).Replace("`r`n", "`n")
|
||||
$bytes = [System.Text.UTF8Encoding]::new($false).GetBytes($text)
|
||||
$sha256 = [System.Security.Cryptography.SHA256]::Create()
|
||||
try {
|
||||
return [System.BitConverter]::ToString($sha256.ComputeHash($bytes)).Replace("-", "")
|
||||
} finally {
|
||||
$sha256.Dispose()
|
||||
}
|
||||
}
|
||||
|
||||
$stream = [System.IO.File]::OpenRead($Path)
|
||||
try {
|
||||
@@ -163,15 +185,16 @@ function Update-Manifest {
|
||||
$path = Join-Path $thirdPartyRoot $relativeRoot
|
||||
Get-ChildItem -LiteralPath $path -File -Recurse | ForEach-Object {
|
||||
$relative = $_.FullName.Substring($thirdPartyRoot.Length + 1).Replace("\", "/")
|
||||
$normalize = $relative.StartsWith("sdl2/include/", [System.StringComparison]::Ordinal)
|
||||
[ordered]@{
|
||||
path = $relative
|
||||
sha256 = Get-Sha256 $_.FullName
|
||||
sha256 = Get-Sha256 -Path $_.FullName -NormalizeLineEndings:$normalize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$metadata.configuration = $Configuration
|
||||
$metadata.files = @($files | Sort-Object path)
|
||||
$metadata.files = @($files | Sort-Object { $_['path'] })
|
||||
$json = $metadata | ConvertTo-Json -Depth 10
|
||||
[System.IO.File]::WriteAllText($manifestPath, "$json`r`n", [System.Text.UTF8Encoding]::new($false))
|
||||
}
|
||||
@@ -184,22 +207,30 @@ Ensure-GitSource `
|
||||
-Repository $metadata.sources.sdl2.repository `
|
||||
-Revision $metadata.sources.sdl2.commit `
|
||||
-Path $sdlSource `
|
||||
-SnapshotRevision $metadata.sources.sdl2.revision
|
||||
-AllowTrackedChanges
|
||||
|
||||
$sdlPatch = Join-Path $thirdPartyRoot $metadata.sources.sdl2.patch
|
||||
Push-Location $sdlSource
|
||||
try {
|
||||
& git apply --reverse --check $sdlPatch 2>$null
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Invoke-Tool git apply --check $sdlPatch
|
||||
Invoke-Tool git apply $sdlPatch
|
||||
& git apply --unidiff-zero --reverse --check $sdlPatch 2>$null
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Invoke-Tool git apply --unidiff-zero --reverse $sdlPatch
|
||||
try {
|
||||
Assert-GitSourceClean -Name "SDL2" -Path $sdlSource
|
||||
} finally {
|
||||
Invoke-Tool git apply --unidiff-zero $sdlPatch
|
||||
}
|
||||
} else {
|
||||
Assert-GitSourceClean -Name "SDL2" -Path $sdlSource
|
||||
Invoke-Tool git apply --unidiff-zero --check $sdlPatch
|
||||
Invoke-Tool git apply --unidiff-zero $sdlPatch
|
||||
}
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
Write-Host "Building SDL2..."
|
||||
& (Join-Path $PSScriptRoot "build-sdl2-angle.ps1") `
|
||||
& (Join-Path $PSScriptRoot "build_sdl2_angle.ps1") `
|
||||
-Configuration $Configuration `
|
||||
-WindowsSdkVersion $WindowsSdkVersion
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
@@ -375,15 +406,31 @@ foreach ($license in $metadata.sources.vcpkg.licenses.PSObject.Properties) {
|
||||
|
||||
Write-Host "Updating dependency hashes..."
|
||||
Update-Manifest
|
||||
& (Join-Path $PSScriptRoot "verify-dependencies.ps1") -Manifest $manifestPath
|
||||
& (Join-Path $PSScriptRoot "verify_dependencies.ps1") -Manifest $manifestPath
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Dependency verification failed with exit code $LASTEXITCODE."
|
||||
}
|
||||
|
||||
if (-not $SkipPackage) {
|
||||
Write-Host "Building the Release package..."
|
||||
Invoke-Tool cmake --preset uwp-release -S $portRoot
|
||||
Invoke-Tool cmake --build --preset uwp-release
|
||||
$gitRoot = Split-Path -Parent (Split-Path -Parent (Get-Command git).Source)
|
||||
$bash = Join-Path $gitRoot "bin\bash.exe"
|
||||
if (-not (Test-Path -LiteralPath $bash -PathType Leaf)) {
|
||||
throw "Git Bash was not found at $bash."
|
||||
}
|
||||
|
||||
$buildScript = [System.IO.Path]::GetFullPath(
|
||||
(Join-Path $portRoot "..\..\scripts\build_xbox_uwp.sh")
|
||||
).Replace("\", "/")
|
||||
if ($buildScript -match "^([A-Za-z]):/(.*)$") {
|
||||
$buildScript = "/$($Matches[1].ToLowerInvariant())/$($Matches[2])"
|
||||
}
|
||||
$packageConfiguration = if ($Configuration -eq "RelWithDebInfo") {
|
||||
"--relwithdebinfo"
|
||||
} else {
|
||||
"--release"
|
||||
}
|
||||
Invoke-Tool $bash $buildScript $packageConfiguration
|
||||
}
|
||||
|
||||
Write-Host "UWP dependencies rebuilt and staged successfully."
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bash
|
||||
# Offline checks for the Xbox UWP build entry points.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=common.sh
|
||||
. "$SCRIPT_DIR/common.sh"
|
||||
|
||||
require_command zip
|
||||
require_command unzip
|
||||
|
||||
say "checking shell entry points"
|
||||
bash -n "$ROOT/scripts/build_xbox_uwp.sh" "$SCRIPT_DIR"/*.sh
|
||||
help="$(bash "$ROOT/scripts/build_xbox_uwp.sh" --help)"
|
||||
printf '%s' "$help" | grep -q -- '--version X.Y.Z' \
|
||||
|| fail "build help does not document --version"
|
||||
|
||||
say "checking the shared game.love payload"
|
||||
temp_dir="$(mktemp -d "${TMPDIR:-/tmp}/gen1recomp-uwp-selftest.XXXXXX")"
|
||||
trap 'rm -rf "$temp_dir"' EXIT
|
||||
love_file="$temp_dir/game.love"
|
||||
listing="$temp_dir/love-listing.txt"
|
||||
"$ROOT/scripts/pack_love.sh" \
|
||||
--output "$love_file" \
|
||||
--listing "$listing" \
|
||||
--version 1.2.3 \
|
||||
--dry-run >/dev/null
|
||||
unzip -p "$love_file" src/core/Version.lua \
|
||||
| grep -Eq 'engine[[:space:]]*=[[:space:]]*"1\.2\.3"' \
|
||||
|| fail "shared payload version was not stamped"
|
||||
|
||||
say "checking the manifest template"
|
||||
grep -q '@UWP_PACKAGE_VERSION@' "$UWP_ROOT/Package.appxmanifest.in" \
|
||||
|| fail "manifest template is missing the package version placeholder"
|
||||
grep -q '@UWP_PUBLISHER_XML@' "$UWP_ROOT/Package.appxmanifest.in" \
|
||||
|| fail "manifest template is missing the publisher placeholder"
|
||||
|
||||
bash "$SCRIPT_DIR/write_build_info.sh" \
|
||||
"$temp_dir/build-info.json" 1.2.3 Release >/dev/null
|
||||
grep -q '"version": "1.2.3"' "$temp_dir/build-info.json" \
|
||||
|| fail "build metadata does not contain the requested version"
|
||||
|
||||
say "Xbox UWP self-test passed"
|
||||
@@ -0,0 +1,150 @@
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory)][ValidatePattern('^\d+\.\d+\.\d+$')]
|
||||
[string]$Version,
|
||||
[ValidateSet('Release', 'RelWithDebInfo')]
|
||||
[string]$Configuration = 'Release',
|
||||
[string]$PackageRoot,
|
||||
[string]$OutputRoot,
|
||||
[string]$BuildInfo,
|
||||
[string]$CertificatePath,
|
||||
[string]$CertificatePassword
|
||||
)
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$repositoryRoot = [System.IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..\..'))
|
||||
$configurationDirectory = $Configuration.ToLowerInvariant()
|
||||
if (-not $PackageRoot) {
|
||||
$PackageRoot = Join-Path $repositoryRoot "ports\uwp\build\$configurationDirectory\AppPackages\Gen1RecompUWP"
|
||||
}
|
||||
if (-not $OutputRoot) {
|
||||
$OutputRoot = Join-Path $repositoryRoot 'dist\xbox-uwp'
|
||||
}
|
||||
|
||||
$packageVersion = "$Version.0"
|
||||
$packageDirectory = Join-Path $PackageRoot "Gen1RecompUWP_${packageVersion}_x64_Test"
|
||||
$package = Join-Path $packageDirectory "Gen1RecompUWP_${packageVersion}_x64.msix"
|
||||
if (-not (Test-Path -LiteralPath $package -PathType Leaf)) {
|
||||
throw "Expected MSIX was not found: $package"
|
||||
}
|
||||
|
||||
function Get-SignTool {
|
||||
$kitsRoot = ${env:ProgramFiles(x86)}
|
||||
if (-not $kitsRoot) {
|
||||
throw 'ProgramFiles(x86) is not defined.'
|
||||
}
|
||||
$binRoot = Join-Path $kitsRoot 'Windows Kits\10\bin'
|
||||
$tool = Get-ChildItem -LiteralPath $binRoot -Filter signtool.exe -File -Recurse |
|
||||
Where-Object { $_.FullName -match '\\x64\\signtool\.exe$' } |
|
||||
Sort-Object FullName -Descending |
|
||||
Select-Object -First 1
|
||||
if (-not $tool) {
|
||||
throw 'SignTool was not found in the Windows SDK.'
|
||||
}
|
||||
return $tool.FullName
|
||||
}
|
||||
|
||||
$certificate = $null
|
||||
if ($CertificatePath) {
|
||||
if (-not (Test-Path -LiteralPath $CertificatePath -PathType Leaf)) {
|
||||
throw "Signing certificate was not found: $CertificatePath"
|
||||
}
|
||||
$flags = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::EphemeralKeySet
|
||||
$certificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new(
|
||||
$CertificatePath,
|
||||
$CertificatePassword,
|
||||
$flags
|
||||
)
|
||||
|
||||
Add-Type -AssemblyName System.IO.Compression
|
||||
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
||||
$archive = [System.IO.Compression.ZipFile]::OpenRead($package)
|
||||
try {
|
||||
$entry = $archive.GetEntry('AppxManifest.xml')
|
||||
if (-not $entry) { throw 'AppxManifest.xml is missing from the MSIX.' }
|
||||
$reader = [System.IO.StreamReader]::new($entry.Open())
|
||||
try { [xml]$manifest = $reader.ReadToEnd() } finally { $reader.Dispose() }
|
||||
} finally {
|
||||
$archive.Dispose()
|
||||
}
|
||||
$publisher = $manifest.Package.Identity.Publisher
|
||||
if ($publisher -ne $certificate.Subject) {
|
||||
throw "Manifest publisher '$publisher' does not match certificate subject '$($certificate.Subject)'."
|
||||
}
|
||||
|
||||
$signTool = Get-SignTool
|
||||
$signArguments = @('sign', '/fd', 'SHA256', '/f', $CertificatePath)
|
||||
if ($CertificatePassword) {
|
||||
$signArguments += @('/p', $CertificatePassword)
|
||||
}
|
||||
$signArguments += $package
|
||||
& $signTool @signArguments
|
||||
if ($LASTEXITCODE -ne 0) { throw "SignTool failed with exit code $LASTEXITCODE." }
|
||||
& $signTool verify /pa $package
|
||||
if ($LASTEXITCODE -ne 0) { throw "Signature verification failed with exit code $LASTEXITCODE." }
|
||||
}
|
||||
|
||||
New-Item -ItemType Directory -Path $OutputRoot -Force | Out-Null
|
||||
$stage = Join-Path $OutputRoot 'stage'
|
||||
if (Test-Path -LiteralPath $stage) {
|
||||
Remove-Item -LiteralPath $stage -Recurse -Force
|
||||
}
|
||||
New-Item -ItemType Directory -Path $stage | Out-Null
|
||||
|
||||
$releasePackage = "gen1recomp-$Version-xbox-uwp.msix"
|
||||
Copy-Item -LiteralPath $package -Destination (Join-Path $stage $releasePackage)
|
||||
$dependencies = Join-Path $packageDirectory 'Dependencies\x64'
|
||||
if (Test-Path -LiteralPath $dependencies -PathType Container) {
|
||||
$dependencyStage = Join-Path $stage 'Dependencies\x64'
|
||||
New-Item -ItemType Directory -Path $dependencyStage -Force | Out-Null
|
||||
Copy-Item -Path (Join-Path $dependencies '*') -Destination $dependencyStage -Recurse
|
||||
}
|
||||
if ($BuildInfo -and (Test-Path -LiteralPath $BuildInfo -PathType Leaf)) {
|
||||
Copy-Item -LiteralPath $BuildInfo -Destination (Join-Path $stage 'build-info.json')
|
||||
}
|
||||
if ($certificate) {
|
||||
[System.IO.File]::WriteAllBytes(
|
||||
(Join-Path $stage 'Gen1RecompUWP.cer'),
|
||||
$certificate.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Cert)
|
||||
)
|
||||
}
|
||||
|
||||
$install = @"
|
||||
Gen1Recomp $Version for Xbox Dev Mode
|
||||
|
||||
Install the MSIX and any packages under Dependencies through Xbox Device Portal.
|
||||
The certificate is public and is included only when the package was release-signed.
|
||||
ROMs, saves and mods are not included.
|
||||
"@
|
||||
[System.IO.File]::WriteAllText(
|
||||
(Join-Path $stage 'INSTALL.txt'),
|
||||
$install,
|
||||
[System.Text.UTF8Encoding]::new($false)
|
||||
)
|
||||
|
||||
$archivePath = Join-Path $OutputRoot "gen1recomp-$Version-xbox-uwp.zip"
|
||||
if (Test-Path -LiteralPath $archivePath) {
|
||||
Remove-Item -LiteralPath $archivePath -Force
|
||||
}
|
||||
Compress-Archive -Path (Join-Path $stage '*') -DestinationPath $archivePath -CompressionLevel Optimal
|
||||
$stream = [System.IO.File]::OpenRead($archivePath)
|
||||
try {
|
||||
$sha256 = [System.Security.Cryptography.SHA256]::Create()
|
||||
try {
|
||||
$hash = ([System.BitConverter]::ToString($sha256.ComputeHash($stream))).Replace('-', '').ToLowerInvariant()
|
||||
} finally {
|
||||
$sha256.Dispose()
|
||||
}
|
||||
} finally {
|
||||
$stream.Dispose()
|
||||
}
|
||||
[System.IO.File]::WriteAllText(
|
||||
"$archivePath.sha256",
|
||||
"$hash $([System.IO.Path]::GetFileName($archivePath))`n",
|
||||
[System.Text.UTF8Encoding]::new($false)
|
||||
)
|
||||
|
||||
Remove-Item -LiteralPath $stage -Recurse -Force
|
||||
Write-Host "Staged $archivePath"
|
||||
@@ -0,0 +1,55 @@
|
||||
param(
|
||||
[string]$Manifest = (Join-Path $PSScriptRoot "..\..\ports\uwp\third_party\manifest.json")
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$manifestPath = (Resolve-Path $Manifest).Path
|
||||
$thirdPartyRoot = Split-Path -Parent $manifestPath
|
||||
$metadata = Get-Content -Raw $manifestPath | ConvertFrom-Json
|
||||
|
||||
function Get-Sha256 {
|
||||
param(
|
||||
[Parameter(Mandatory)][string]$Path,
|
||||
[switch]$NormalizeLineEndings
|
||||
)
|
||||
|
||||
if ($NormalizeLineEndings) {
|
||||
$bytes = [System.IO.File]::ReadAllBytes($Path)
|
||||
$text = [System.Text.Encoding]::UTF8.GetString($bytes).Replace("`r`n", "`n")
|
||||
$bytes = [System.Text.UTF8Encoding]::new($false).GetBytes($text)
|
||||
$sha256 = [System.Security.Cryptography.SHA256]::Create()
|
||||
try {
|
||||
return [System.BitConverter]::ToString($sha256.ComputeHash($bytes)).Replace("-", "")
|
||||
} finally {
|
||||
$sha256.Dispose()
|
||||
}
|
||||
}
|
||||
|
||||
$stream = [System.IO.File]::OpenRead($Path)
|
||||
try {
|
||||
$sha256 = [System.Security.Cryptography.SHA256]::Create()
|
||||
try {
|
||||
return [System.BitConverter]::ToString($sha256.ComputeHash($stream)).Replace("-", "")
|
||||
} finally {
|
||||
$sha256.Dispose()
|
||||
}
|
||||
} finally {
|
||||
$stream.Dispose()
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($file in $metadata.files) {
|
||||
$path = Join-Path $thirdPartyRoot $file.path
|
||||
if (-not (Test-Path -LiteralPath $path -PathType Leaf)) {
|
||||
throw "Missing UWP dependency: $($file.path)"
|
||||
}
|
||||
|
||||
$normalize = $file.path.StartsWith("sdl2/include/", [System.StringComparison]::Ordinal)
|
||||
$actual = Get-Sha256 -Path $path -NormalizeLineEndings:$normalize
|
||||
if ($actual -ne $file.sha256) {
|
||||
throw "UWP dependency hash mismatch: $($file.path)"
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Verified $($metadata.files.Count) UWP dependency files."
|
||||
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env bash
|
||||
# Write provenance for an Xbox UWP package.
|
||||
#
|
||||
# Usage: scripts/xbox-uwp/write_build_info.sh OUTPUT VERSION CONFIGURATION
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=common.sh
|
||||
. "$SCRIPT_DIR/common.sh"
|
||||
|
||||
OUTPUT="${1:-}"
|
||||
VERSION="${2:-}"
|
||||
CONFIGURATION="${3:-}"
|
||||
MANIFEST="$UWP_ROOT/third_party/manifest.json"
|
||||
|
||||
[ -n "$OUTPUT" ] && [ -n "$VERSION" ] && [ -n "$CONFIGURATION" ] \
|
||||
|| fail "usage: $0 OUTPUT VERSION CONFIGURATION"
|
||||
[ -f "$MANIFEST" ] || fail "missing dependency manifest: $MANIFEST"
|
||||
|
||||
mkdir -p "$(dirname "$OUTPUT")"
|
||||
GIT_COMMIT="$(git -C "$ROOT" rev-parse HEAD 2>/dev/null || echo unknown)"
|
||||
BUILT_AT="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||
MANIFEST_SHA256="$(sha256_file "$MANIFEST")"
|
||||
LOVE_COMMIT="$(awk '
|
||||
/"love"[[:space:]]*:/ { in_love=1 }
|
||||
in_love && /"commit"[[:space:]]*:/ {
|
||||
value=$0
|
||||
sub(/^.*"commit"[[:space:]]*:[[:space:]]*"/, "", value)
|
||||
sub(/".*$/, "", value)
|
||||
print value
|
||||
exit
|
||||
}
|
||||
' "$MANIFEST")"
|
||||
[ -n "$LOVE_COMMIT" ] || fail "LÖVE revision is missing from the dependency manifest"
|
||||
|
||||
cat > "$OUTPUT" <<EOF
|
||||
{
|
||||
"platform": "xbox-uwp",
|
||||
"version": "$VERSION",
|
||||
"configuration": "$CONFIGURATION",
|
||||
"gitCommit": "$GIT_COMMIT",
|
||||
"loveCommit": "$LOVE_COMMIT",
|
||||
"dependencyManifestSha256": "$MANIFEST_SHA256",
|
||||
"builtAt": "$BUILT_AT"
|
||||
}
|
||||
EOF
|
||||
|
||||
say "build info: $OUTPUT"
|
||||
@@ -1,4 +1,4 @@
|
||||
-- Platform capability detection for NX / mobile / desktop.
|
||||
-- Platform capability detection for console, mobile and desktop builds.
|
||||
|
||||
local Platform = {}
|
||||
|
||||
@@ -8,20 +8,22 @@ local function compute()
|
||||
local osName = (love and love.system and love.system.getOS and love.system.getOS())
|
||||
or "Unknown"
|
||||
local nx = osName == "NX"
|
||||
local uwp = osName == "UWP"
|
||||
local mobile = osName == "Android" or osName == "iOS"
|
||||
local nativePicker = love and love.system
|
||||
and type(love.system.pickFile) == "function"
|
||||
return {
|
||||
os = osName,
|
||||
nx = nx,
|
||||
uwp = uwp,
|
||||
mobile = mobile,
|
||||
console = nx,
|
||||
console = nx or uwp,
|
||||
hasNativePicker = nativePicker,
|
||||
canSpawnProcess = osName == "OS X" or osName == "Windows" or osName == "Linux",
|
||||
romImportMode = nx and "save-directory"
|
||||
or (nativePicker and "native-picker")
|
||||
or "desktop",
|
||||
networkValidated = not nx,
|
||||
networkValidated = not nx and not uwp,
|
||||
}
|
||||
end
|
||||
|
||||
@@ -34,6 +36,10 @@ function Platform.isNX()
|
||||
return Platform.detect().nx
|
||||
end
|
||||
|
||||
function Platform.isUWP()
|
||||
return Platform.detect().uwp
|
||||
end
|
||||
|
||||
function Platform.romImportMode()
|
||||
return Platform.detect().romImportMode
|
||||
end
|
||||
|
||||
@@ -28,14 +28,10 @@
|
||||
-- ordinary love.filesystem/save-directory behaviour.
|
||||
|
||||
local CacheFs = {}
|
||||
local Platform = require("src.core.Platform")
|
||||
|
||||
local SEP = package.config:sub(1, 1)
|
||||
|
||||
local function isUWP()
|
||||
return love and love.system and love.system.getOS
|
||||
and love.system.getOS() == "UWP"
|
||||
end
|
||||
|
||||
-- Cache-relative paths are prefixed with this before every read/write, so a
|
||||
-- Blue/Yellow import lands under its GameVersion.cachePrefix (blue/, yellow/)
|
||||
-- while a Red import keeps the historical root. The launcher sets it per
|
||||
@@ -57,7 +53,7 @@ local mkdirFn = nil
|
||||
local function resolveMkdir()
|
||||
if mkdirFn ~= nil then return mkdirFn end
|
||||
mkdirFn = false
|
||||
if isUWP() then return mkdirFn end
|
||||
if Platform.isUWP() then return mkdirFn end
|
||||
local ok, ffi = pcall(require, "ffi")
|
||||
if not ok then return mkdirFn end
|
||||
if ffi.os == "Windows" then
|
||||
@@ -89,7 +85,7 @@ local rmdirFn = nil
|
||||
local function resolveRmdir()
|
||||
if rmdirFn ~= nil then return rmdirFn end
|
||||
rmdirFn = false
|
||||
if isUWP() then return rmdirFn end
|
||||
if Platform.isUWP() then return rmdirFn end
|
||||
local ok, ffi = pcall(require, "ffi")
|
||||
if not ok then return rmdirFn end
|
||||
if ffi.os == "Windows" then
|
||||
|
||||
+21
-27
@@ -8,11 +8,6 @@ local SafeArea = require("src.core.SafeArea")
|
||||
local RomImporter = {}
|
||||
RomImporter.__index = RomImporter
|
||||
|
||||
local function isUWP()
|
||||
return love and love.system and love.system.getOS
|
||||
and love.system.getOS() == "UWP"
|
||||
end
|
||||
|
||||
-- love.system.pickFile is a NATIVE BRIDGE, not part of LÖVE: it exists only on
|
||||
-- builds that compiled one (Android, and iOS builds patched by
|
||||
-- mobile/ios/patch_love_src.py). A build without it must fall back to the
|
||||
@@ -995,7 +990,6 @@ end
|
||||
-- import-only run all skip the release check so headless and CI runs never spin
|
||||
-- up the background worker or reach out to the network.
|
||||
local function updaterAllowed()
|
||||
if isUWP() then return false end
|
||||
if not Platform.networkValidated() then return false end
|
||||
if not (love.filesystem.isFused and love.filesystem.isFused()) then return false end
|
||||
if os.getenv("POKEPORT_AUTOPILOT") or os.getenv("POKEPORT_DRIVER") then return false end
|
||||
@@ -1100,8 +1094,8 @@ function RomImporter.new(onComplete, opts)
|
||||
-- Android SAF create-document: which game's SAVE FILES card should show
|
||||
-- "Save exported." when export_done.flag appears on focus.
|
||||
androidPendingExportVersion = nil,
|
||||
iosPendingKind = nil,
|
||||
iosPendingVersion = nil,
|
||||
pickerPendingKind = nil,
|
||||
pickerPendingVersion = nil,
|
||||
-- Virtual pointer for handhelds / gamepads (Anbernic stock OS has no
|
||||
-- mouse). D-pad + left stick move it; A clicks; shoulders cycle tabs;
|
||||
-- right stick scrolls the save-slot / mods lists.
|
||||
@@ -1501,9 +1495,9 @@ function RomImporter:chooseMod()
|
||||
return
|
||||
end
|
||||
if self.nativePicker and love.system.getPickedFile then
|
||||
self.iosPendingKind = "mod"
|
||||
self.pickerPendingKind = "mod"
|
||||
if not pickFile("mod") then
|
||||
self.iosPendingKind = nil
|
||||
self.pickerPendingKind = nil
|
||||
self.modNotice = { ok = false, text = "Could not open the file picker." }
|
||||
end
|
||||
return
|
||||
@@ -1577,11 +1571,11 @@ function RomImporter:chooseSaveImport(version)
|
||||
return
|
||||
end
|
||||
if self.nativePicker and love.system.getPickedFile then
|
||||
self.iosPendingKind = "sav"
|
||||
self.iosPendingVersion = version
|
||||
self.pickerPendingKind = "sav"
|
||||
self.pickerPendingVersion = version
|
||||
if not pickFile("sav") then
|
||||
self.iosPendingKind = nil
|
||||
self.iosPendingVersion = nil
|
||||
self.pickerPendingKind = nil
|
||||
self.pickerPendingVersion = nil
|
||||
self.saveNotice[version] = { ok = false, text = "Could not open the file picker." }
|
||||
end
|
||||
return
|
||||
@@ -1695,9 +1689,9 @@ function RomImporter:choose(version)
|
||||
return
|
||||
end
|
||||
if self.nativePicker and love.system.getPickedFile then
|
||||
self.iosPendingKind = "rom"
|
||||
self.pickerPendingKind = "rom"
|
||||
if not pickFile("rom") then
|
||||
self.iosPendingKind = nil
|
||||
self.pickerPendingKind = nil
|
||||
self:setError("Could not open the file picker.")
|
||||
end
|
||||
return
|
||||
@@ -1899,32 +1893,32 @@ function RomImporter:update(dt)
|
||||
if self.nativePicker and love.system.getPickedFile and self.workState ~= "working" then
|
||||
local path = love.system.getPickedFile()
|
||||
if path then
|
||||
local kind = self.iosPendingKind or "rom"
|
||||
local version = self.iosPendingVersion
|
||||
self.iosPendingKind = nil
|
||||
self.iosPendingVersion = nil
|
||||
local kind = self.pickerPendingKind or "rom"
|
||||
local version = self.pickerPendingVersion
|
||||
self.pickerPendingKind = nil
|
||||
self.pickerPendingVersion = nil
|
||||
if kind == "mod" then
|
||||
self:_installMod(path)
|
||||
if isUWP() and self.modNotice and self.modNotice.ok then
|
||||
if Platform.isUWP() and self.modNotice and self.modNotice.ok then
|
||||
os.remove(path)
|
||||
end
|
||||
elseif kind == "sav" then
|
||||
local target = version or self:_savedropTarget()
|
||||
self:_importSave(target, path)
|
||||
if isUWP() and self.saveNotice[target] and self.saveNotice[target].ok then
|
||||
if Platform.isUWP() and self.saveNotice[target] and self.saveNotice[target].ok then
|
||||
os.remove(path)
|
||||
end
|
||||
else
|
||||
self:startPath(path)
|
||||
if isUWP() then os.remove(path) end
|
||||
if Platform.isUWP() then os.remove(path) end
|
||||
end
|
||||
elseif love.system.getPickError then
|
||||
local errorText = love.system.getPickError()
|
||||
if errorText then
|
||||
local kind = self.iosPendingKind or "rom"
|
||||
local version = self.iosPendingVersion or self:_savedropTarget()
|
||||
self.iosPendingKind = nil
|
||||
self.iosPendingVersion = nil
|
||||
local kind = self.pickerPendingKind or "rom"
|
||||
local version = self.pickerPendingVersion or self:_savedropTarget()
|
||||
self.pickerPendingKind = nil
|
||||
self.pickerPendingVersion = nil
|
||||
if kind == "mod" then
|
||||
self.modNotice = { ok = false, text = errorText }
|
||||
elseif kind == "sav" then
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
-- worker can reuse the exact same code path via love.filesystem.load.
|
||||
|
||||
local Check = {}
|
||||
local Platform = require("src.core.Platform")
|
||||
|
||||
Check.REPO = "bryanthaboi/gen1recomp"
|
||||
|
||||
@@ -99,8 +100,7 @@ local cache = { status = "idle" } -- newest snapshot from the worker
|
||||
|
||||
local function ensureWorker()
|
||||
if workerReady ~= nil then return workerReady end
|
||||
if love and love.system and love.system.getOS
|
||||
and love.system.getOS() == "UWP" then
|
||||
if not Platform.networkValidated() then
|
||||
workerReady = false
|
||||
return false
|
||||
end
|
||||
|
||||
@@ -37,6 +37,19 @@ withOS("NX", nil, function(Platform)
|
||||
eq(Platform.romImportMode(), "save-directory", "romImportMode helper")
|
||||
end)
|
||||
|
||||
-- Xbox UWP: native picker, console constraints, no in-app updater
|
||||
withOS("UWP", function() end, function(Platform)
|
||||
local caps = Platform.detect()
|
||||
eq(caps.os, "UWP", "UWP detect os")
|
||||
eq(caps.uwp, true, "UWP flag")
|
||||
eq(caps.console, true, "UWP console")
|
||||
eq(caps.hasNativePicker, true, "UWP has pickFile")
|
||||
eq(caps.romImportMode, "native-picker", "UWP romImportMode")
|
||||
eq(caps.canSpawnProcess, false, "UWP cannot spawn processes")
|
||||
eq(caps.networkValidated, false, "UWP network not validated")
|
||||
eq(Platform.isUWP(), true, "isUWP convenience")
|
||||
end)
|
||||
|
||||
-- Android: mobile native picker path, not NX semantics
|
||||
withOS("Android", function() end, function(Platform)
|
||||
local caps = Platform.detect()
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package.path = "./?.lua;./?/init.lua;" .. package.path
|
||||
if not _G.love then _G.love = require("tests.love_stub") end
|
||||
|
||||
local S = require("tests.harness").suite("UWP native picker")
|
||||
local check = S.check
|
||||
|
||||
local Platform = require("src.core.Platform")
|
||||
local RomImporter = require("src.import.RomImporter")
|
||||
|
||||
love.system = love.system or {}
|
||||
local saved = {
|
||||
getOS = love.system.getOS,
|
||||
pickFile = love.system.pickFile,
|
||||
getPickedFile = love.system.getPickedFile,
|
||||
getPickError = love.system.getPickError,
|
||||
remove = os.remove,
|
||||
}
|
||||
|
||||
love.system.getOS = function() return "UWP" end
|
||||
love.system.pickFile = function() return true end
|
||||
love.system.getPickedFile = function()
|
||||
love.system.getPickedFile = function() return nil end
|
||||
return [[C:\LocalState\picked_mod.zip]]
|
||||
end
|
||||
love.system.getPickError = function() return nil end
|
||||
|
||||
local removedPath
|
||||
os.remove = function(path)
|
||||
removedPath = path
|
||||
return true
|
||||
end
|
||||
|
||||
Platform._resetForTests()
|
||||
local importer = RomImporter.new(function() end, { launcher = true })
|
||||
importer.pickerPendingKind = "mod"
|
||||
importer._installMod = function(self, source)
|
||||
self.installedPath = source
|
||||
self.modNotice = { ok = true, text = "Installed test-mod" }
|
||||
end
|
||||
importer:update(0)
|
||||
|
||||
check(importer.installedPath == [[C:\LocalState\picked_mod.zip]],
|
||||
"passes the picked path to the mod installer")
|
||||
check(removedPath == [[C:\LocalState\picked_mod.zip]],
|
||||
"removes the temporary copy after installation")
|
||||
|
||||
love.system.getOS = saved.getOS
|
||||
love.system.pickFile = saved.pickFile
|
||||
love.system.getPickedFile = saved.getPickedFile
|
||||
love.system.getPickError = saved.getPickError
|
||||
os.remove = saved.remove
|
||||
Platform._resetForTests()
|
||||
|
||||
S.finish()
|
||||
@@ -23,6 +23,7 @@ local S = require("tests.harness").suite("rom importer double pick (#553)")
|
||||
local check = S.check
|
||||
|
||||
local RomImporter = require("src.import.RomImporter")
|
||||
local Platform = require("src.core.Platform")
|
||||
|
||||
love.system = love.system or {}
|
||||
local saved = {
|
||||
@@ -53,6 +54,7 @@ love.filesystem.remove = function(name) saveDir[name] = nil; return true end
|
||||
|
||||
local function importer(os)
|
||||
love.system.getOS = function() return os end
|
||||
Platform._resetForTests()
|
||||
local ri = RomImporter.new(function() end, { launcher = true })
|
||||
ri.ready = { red = false, blue = false, yellow = false }
|
||||
return ri
|
||||
@@ -68,6 +70,7 @@ local ios = importer("iOS")
|
||||
check(ios.pickPending, "iOS still boots armed (unchanged by this fix)")
|
||||
|
||||
love.system.getOS = function() return "OS X" end
|
||||
Platform._resetForTests()
|
||||
local desktop = RomImporter.new(function() end, { launcher = true })
|
||||
check(not desktop.pickPending, "desktop does not poll: it has no save-dir picks")
|
||||
|
||||
@@ -137,29 +140,6 @@ contract:choose("red")
|
||||
check(picks == 2,
|
||||
"choose() still reopens the picker per call (#420/#442 contract, got " .. picks .. ")")
|
||||
|
||||
-- 7. UWP consumes the absolute LocalState path returned by its native picker
|
||||
-- and removes the temporary copy only after a successful import.
|
||||
local removedPath
|
||||
local savedOsRemove = os.remove
|
||||
os.remove = function(path) removedPath = path; return true end
|
||||
love.system.getPickedFile = function()
|
||||
love.system.getPickedFile = function() return nil end
|
||||
return [[C:\LocalState\picked_mod.zip]]
|
||||
end
|
||||
love.system.getPickError = function() return nil end
|
||||
local uwp = importer("UWP")
|
||||
uwp.iosPendingKind = "mod"
|
||||
uwp._installMod = function(self, source)
|
||||
self._installed = source
|
||||
self.modNotice = { ok = true, text = "Installed test-mod" }
|
||||
end
|
||||
uwp:update(0)
|
||||
check(uwp._installed == [[C:\LocalState\picked_mod.zip]],
|
||||
"UWP passes the picker path to the mod installer")
|
||||
check(removedPath == [[C:\LocalState\picked_mod.zip]],
|
||||
"UWP removes the temporary picker copy after installation")
|
||||
os.remove = savedOsRemove
|
||||
|
||||
local touchForwardsToImporter = {
|
||||
Android = true,
|
||||
iOS = true,
|
||||
@@ -192,5 +172,6 @@ love.filesystem.getDirectoryItems = saved.getDirectoryItems
|
||||
love.filesystem.getInfo = saved.getInfo
|
||||
love.filesystem.read = saved.read
|
||||
love.filesystem.remove = saved.remove
|
||||
Platform._resetForTests()
|
||||
|
||||
S.finish()
|
||||
|
||||
Reference in New Issue
Block a user