exp-runtime 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- exp_runtime-0.5.0/.github/workflows/desktop-builds.yml +259 -0
- exp_runtime-0.5.0/.github/workflows/ios-builds.yml +103 -0
- exp_runtime-0.5.0/.gitignore +68 -0
- exp_runtime-0.5.0/AGENTS.md +75 -0
- exp_runtime-0.5.0/CHANGELOG.md +359 -0
- exp_runtime-0.5.0/LICENSE +21 -0
- exp_runtime-0.5.0/MAINTAINERS.md +265 -0
- exp_runtime-0.5.0/MANIFEST.in +41 -0
- exp_runtime-0.5.0/PKG-INFO +287 -0
- exp_runtime-0.5.0/README.md +229 -0
- exp_runtime-0.5.0/RELEASE.md +16 -0
- exp_runtime-0.5.0/docs/COD.md +421 -0
- exp_runtime-0.5.0/docs/DEVELOPMENT.md +135 -0
- exp_runtime-0.5.0/docs/DISTRIBUTION.md +224 -0
- exp_runtime-0.5.0/docs/ENGINE_ABI.md +507 -0
- exp_runtime-0.5.0/docs/EPISODE_CATALOG.md +242 -0
- exp_runtime-0.5.0/docs/FOOTBALL_UI.md +237 -0
- exp_runtime-0.5.0/docs/GRID_UI.md +220 -0
- exp_runtime-0.5.0/docs/IOS_APP.md +291 -0
- exp_runtime-0.5.0/docs/IPA.md +318 -0
- exp_runtime-0.5.0/docs/MAIN_MENU.md +531 -0
- exp_runtime-0.5.0/docs/MINIGAMES.md +484 -0
- exp_runtime-0.5.0/docs/NAME_INPUT.md +136 -0
- exp_runtime-0.5.0/docs/PROVENANCE.md +83 -0
- exp_runtime-0.5.0/docs/RUNTIME.md +785 -0
- exp_runtime-0.5.0/docs/SCHEMA.md +340 -0
- exp_runtime-0.5.0/docs/SDK.md +178 -0
- exp_runtime-0.5.0/docs/STORY_SERVICES.md +959 -0
- exp_runtime-0.5.0/docs/TITLE_SCREENS.md +196 -0
- exp_runtime-0.5.0/docs/UI_ASSETS.md +293 -0
- exp_runtime-0.5.0/docs/UI_FIDELITY.md +1254 -0
- exp_runtime-0.5.0/docs/VM_EXECUTION.md +103 -0
- exp_runtime-0.5.0/docs/VM_SPEC.md +484 -0
- exp_runtime-0.5.0/exp_runtime.egg-info/SOURCES.txt +221 -0
- exp_runtime-0.5.0/ios/EXPRuntime/EXPRuntimeApp.swift +446 -0
- exp_runtime-0.5.0/ios/EXPRuntime/Info.plist +24 -0
- exp_runtime-0.5.0/ios/EXPRuntime/NativeCanvas.swift +271 -0
- exp_runtime-0.5.0/ios/EXPRuntime/NativeFonts.h +2 -0
- exp_runtime-0.5.0/ios/EXPRuntime/NativeFonts.m +148 -0
- exp_runtime-0.5.0/ios/EXPRuntime/PythonBridge.h +12 -0
- exp_runtime-0.5.0/ios/EXPRuntime/PythonBridge.m +101 -0
- exp_runtime-0.5.0/ios/EXPRuntime.xcodeproj/project.pbxproj +250 -0
- exp_runtime-0.5.0/ios/Signing.local.xcconfig.example +5 -0
- exp_runtime-0.5.0/ios/Signing.xcconfig +6 -0
- exp_runtime-0.5.0/ios/dependencies.json +18 -0
- exp_runtime-0.5.0/ios/probe/exp_ios_probe.py +630 -0
- exp_runtime-0.5.0/ios/probe/rar_fixture.py +36 -0
- exp_runtime-0.5.0/packages/cod/LICENSE +21 -0
- exp_runtime-0.5.0/packages/cod/MANIFEST.in +4 -0
- exp_runtime-0.5.0/packages/cod/README.md +15 -0
- exp_runtime-0.5.0/packages/cod/pyproject.toml +20 -0
- exp_runtime-0.5.0/packages/cod/src/exp_runtime/cod/__init__.py +1 -0
- exp_runtime-0.5.0/packages/cod/src/exp_runtime/cod/assets.py +76 -0
- exp_runtime-0.5.0/packages/cod/src/exp_runtime/cod/audio.py +6 -0
- exp_runtime-0.5.0/packages/cod/src/exp_runtime/cod/content.py +7 -0
- exp_runtime-0.5.0/packages/cod/src/exp_runtime/cod/profile.py +36 -0
- exp_runtime-0.5.0/packages/cod/src/exp_runtime/cod/services.py +56 -0
- exp_runtime-0.5.0/packages/engine/LICENSE +21 -0
- exp_runtime-0.5.0/packages/engine/MANIFEST.in +4 -0
- exp_runtime-0.5.0/packages/engine/README.md +15 -0
- exp_runtime-0.5.0/packages/engine/pyproject.toml +23 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/audio.py +13 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/background.py +58 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/character_picker.py +92 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/choice.py +116 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/choice_hints.py +153 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/content.py +742 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/dialogue.py +151 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/dialogue_animation.py +345 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/dialogue_notice.py +51 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/engine.py +609 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/episode_catalog.py +171 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/game_state.py +9 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/games.py +35 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/ios_fonts.py +228 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/launcher.py +92 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/loading.py +37 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/menu.py +177 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/message_panel.py +36 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/minigames.py +76 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/randomness.py +61 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/rar.py +145 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/relationships.py +131 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/runtime.py +879 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/scene_badge.py +65 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/speaker_names.py +258 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/text_input.py +55 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/title_screen.py +104 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/trace.py +76 -0
- exp_runtime-0.5.0/packages/engine/src/exp_runtime/vm.py +391 -0
- exp_runtime-0.5.0/packages/formats/LICENSE +21 -0
- exp_runtime-0.5.0/packages/formats/MANIFEST.in +4 -0
- exp_runtime-0.5.0/packages/formats/README.md +15 -0
- exp_runtime-0.5.0/packages/formats/pyproject.toml +27 -0
- exp_runtime-0.5.0/packages/formats/src/exp_runtime/__main__.py +5 -0
- exp_runtime-0.5.0/packages/formats/src/exp_runtime/atlas.py +203 -0
- exp_runtime-0.5.0/packages/formats/src/exp_runtime/cli.py +186 -0
- exp_runtime-0.5.0/packages/formats/src/exp_runtime/decode/__init__.py +1 -0
- exp_runtime-0.5.0/packages/formats/src/exp_runtime/decode/bytecode.py +119 -0
- exp_runtime-0.5.0/packages/formats/src/exp_runtime/exp.py +121 -0
- exp_runtime-0.5.0/packages/formats/src/exp_runtime/fonts.py +280 -0
- exp_runtime-0.5.0/packages/formats/src/exp_runtime/formats.py +18 -0
- exp_runtime-0.5.0/packages/formats/src/exp_runtime/languages.py +23 -0
- exp_runtime-0.5.0/packages/formats/src/exp_runtime/menu_assets.py +85 -0
- exp_runtime-0.5.0/packages/formats/src/exp_runtime/ui_assets.py +285 -0
- exp_runtime-0.5.0/packages/player/LICENSE +21 -0
- exp_runtime-0.5.0/packages/player/MANIFEST.in +5 -0
- exp_runtime-0.5.0/packages/player/README.md +15 -0
- exp_runtime-0.5.0/packages/player/pyproject.toml +30 -0
- exp_runtime-0.5.0/packages/player/src/exp_runtime/app_icon.py +12 -0
- exp_runtime-0.5.0/packages/player/src/exp_runtime/app_info.py +16 -0
- exp_runtime-0.5.0/packages/player/src/exp_runtime/application.py +825 -0
- exp_runtime-0.5.0/packages/player/src/exp_runtime/assets/kiwi.svg +49 -0
- exp_runtime-0.5.0/packages/player/src/exp_runtime/desktop.py +726 -0
- exp_runtime-0.5.0/packages/player/src/exp_runtime/desktop_choice.py +202 -0
- exp_runtime-0.5.0/packages/player/src/exp_runtime/desktop_dialogue.py +271 -0
- exp_runtime-0.5.0/packages/player/src/exp_runtime/desktop_input.py +176 -0
- exp_runtime-0.5.0/packages/player/src/exp_runtime/desktop_loading.py +45 -0
- exp_runtime-0.5.0/packages/player/src/exp_runtime/desktop_menu.py +448 -0
- exp_runtime-0.5.0/packages/player/src/exp_runtime/desktop_message.py +123 -0
- exp_runtime-0.5.0/packages/player/src/exp_runtime/desktop_pause.py +105 -0
- exp_runtime-0.5.0/packages/player/src/exp_runtime/desktop_picker.py +68 -0
- exp_runtime-0.5.0/packages/player/src/exp_runtime/desktop_text.py +88 -0
- exp_runtime-0.5.0/packages/player/src/exp_runtime/desktop_title.py +82 -0
- exp_runtime-0.5.0/packages/player/src/exp_runtime/graphics.py +79 -0
- exp_runtime-0.5.0/packages/player/src/exp_runtime/platforms/__init__.py +1 -0
- exp_runtime-0.5.0/packages/player/src/exp_runtime/platforms/drawing.py +612 -0
- exp_runtime-0.5.0/packages/player/src/exp_runtime/platforms/ios.py +225 -0
- exp_runtime-0.5.0/packages/player/src/exp_runtime/pointer.py +25 -0
- exp_runtime-0.5.0/packages/player/src/exp_runtime/projection.py +68 -0
- exp_runtime-0.5.0/packages/player/src/exp_runtime/settings.py +46 -0
- exp_runtime-0.5.0/packages/player/src/exp_runtime/updates.py +144 -0
- exp_runtime-0.5.0/packages/shs/LICENSE +21 -0
- exp_runtime-0.5.0/packages/shs/MANIFEST.in +4 -0
- exp_runtime-0.5.0/packages/shs/README.md +15 -0
- exp_runtime-0.5.0/packages/shs/pyproject.toml +20 -0
- exp_runtime-0.5.0/packages/shs/src/exp_runtime/shs/__init__.py +1 -0
- exp_runtime-0.5.0/packages/shs/src/exp_runtime/shs/audio.py +33 -0
- exp_runtime-0.5.0/packages/shs/src/exp_runtime/shs/builtin_episode.py +50 -0
- exp_runtime-0.5.0/packages/shs/src/exp_runtime/shs/content.py +25 -0
- exp_runtime-0.5.0/packages/shs/src/exp_runtime/shs/desktop_football.py +319 -0
- exp_runtime-0.5.0/packages/shs/src/exp_runtime/shs/desktop_grid.py +341 -0
- exp_runtime-0.5.0/packages/shs/src/exp_runtime/shs/football.py +517 -0
- exp_runtime-0.5.0/packages/shs/src/exp_runtime/shs/football_layout.py +164 -0
- exp_runtime-0.5.0/packages/shs/src/exp_runtime/shs/grid_layout.py +78 -0
- exp_runtime-0.5.0/packages/shs/src/exp_runtime/shs/grid_motion.py +41 -0
- exp_runtime-0.5.0/packages/shs/src/exp_runtime/shs/ios_assets.py +100 -0
- exp_runtime-0.5.0/packages/shs/src/exp_runtime/shs/profile.py +37 -0
- exp_runtime-0.5.0/packages/shs/src/exp_runtime/shs/relationships.py +14 -0
- exp_runtime-0.5.0/packages/shs/src/exp_runtime/shs/services.py +114 -0
- exp_runtime-0.5.0/packages/shs/src/exp_runtime/shs/survey.py +45 -0
- exp_runtime-0.5.0/packages/shs/src/exp_runtime/shs/word_grid.py +592 -0
- exp_runtime-0.5.0/pyproject.toml +47 -0
- exp_runtime-0.5.0/setup.cfg +4 -0
- exp_runtime-0.5.0/tests/test_atlas.py +61 -0
- exp_runtime-0.5.0/tests/test_audio.py +407 -0
- exp_runtime-0.5.0/tests/test_background.py +272 -0
- exp_runtime-0.5.0/tests/test_build_query.py +147 -0
- exp_runtime-0.5.0/tests/test_builtin_episode.py +188 -0
- exp_runtime-0.5.0/tests/test_bytecode.py +51 -0
- exp_runtime-0.5.0/tests/test_character_picker.py +169 -0
- exp_runtime-0.5.0/tests/test_choice.py +323 -0
- exp_runtime-0.5.0/tests/test_choice_hints.py +199 -0
- exp_runtime-0.5.0/tests/test_choice_shuffle.py +248 -0
- exp_runtime-0.5.0/tests/test_cod_services.py +302 -0
- exp_runtime-0.5.0/tests/test_components.py +104 -0
- exp_runtime-0.5.0/tests/test_content.py +221 -0
- exp_runtime-0.5.0/tests/test_desktop.py +408 -0
- exp_runtime-0.5.0/tests/test_dialogue.py +356 -0
- exp_runtime-0.5.0/tests/test_dialogue_lifecycle.py +310 -0
- exp_runtime-0.5.0/tests/test_dialogue_notice.py +164 -0
- exp_runtime-0.5.0/tests/test_engine.py +94 -0
- exp_runtime-0.5.0/tests/test_episode_catalog.py +450 -0
- exp_runtime-0.5.0/tests/test_episode_exit.py +311 -0
- exp_runtime-0.5.0/tests/test_episode_rar.py +104 -0
- exp_runtime-0.5.0/tests/test_episode_zip.py +256 -0
- exp_runtime-0.5.0/tests/test_fonts.py +150 -0
- exp_runtime-0.5.0/tests/test_football.py +143 -0
- exp_runtime-0.5.0/tests/test_football_layout.py +257 -0
- exp_runtime-0.5.0/tests/test_games.py +328 -0
- exp_runtime-0.5.0/tests/test_grid_layout.py +166 -0
- exp_runtime-0.5.0/tests/test_ios_fonts.py +76 -0
- exp_runtime-0.5.0/tests/test_ios_host.py +144 -0
- exp_runtime-0.5.0/tests/test_ipa.py +407 -0
- exp_runtime-0.5.0/tests/test_ipa_music.py +282 -0
- exp_runtime-0.5.0/tests/test_label_layout.py +454 -0
- exp_runtime-0.5.0/tests/test_loading.py +191 -0
- exp_runtime-0.5.0/tests/test_menu.py +459 -0
- exp_runtime-0.5.0/tests/test_message_panel.py +169 -0
- exp_runtime-0.5.0/tests/test_minigames.py +127 -0
- exp_runtime-0.5.0/tests/test_named_dialogue.py +267 -0
- exp_runtime-0.5.0/tests/test_native_drawing.py +191 -0
- exp_runtime-0.5.0/tests/test_packaging.py +104 -0
- exp_runtime-0.5.0/tests/test_panel_lifecycle.py +108 -0
- exp_runtime-0.5.0/tests/test_pause_feedback.py +141 -0
- exp_runtime-0.5.0/tests/test_rar_library.py +81 -0
- exp_runtime-0.5.0/tests/test_relationships.py +262 -0
- exp_runtime-0.5.0/tests/test_runtime.py +195 -0
- exp_runtime-0.5.0/tests/test_shared_dialogue.py +192 -0
- exp_runtime-0.5.0/tests/test_shs_services.py +223 -0
- exp_runtime-0.5.0/tests/test_simulator_verification.py +351 -0
- exp_runtime-0.5.0/tests/test_story_services.py +106 -0
- exp_runtime-0.5.0/tests/test_survey.py +259 -0
- exp_runtime-0.5.0/tests/test_text_input.py +264 -0
- exp_runtime-0.5.0/tests/test_title_screen.py +246 -0
- exp_runtime-0.5.0/tests/test_trace.py +64 -0
- exp_runtime-0.5.0/tests/test_ui_assets.py +111 -0
- exp_runtime-0.5.0/tests/test_updates.py +317 -0
- exp_runtime-0.5.0/tests/test_vm.py +126 -0
- exp_runtime-0.5.0/tests/test_word_grid.py +264 -0
- exp_runtime-0.5.0/tools/audit_format.py +167 -0
- exp_runtime-0.5.0/tools/audit_runtime.py +58 -0
- exp_runtime-0.5.0/tools/audit_ui_assets.py +80 -0
- exp_runtime-0.5.0/tools/audit_vm.py +30 -0
- exp_runtime-0.5.0/tools/build_desktop.py +97 -0
- exp_runtime-0.5.0/tools/build_ios.py +233 -0
- exp_runtime-0.5.0/tools/build_packages.py +92 -0
- exp_runtime-0.5.0/tools/build_rar.py +90 -0
- exp_runtime-0.5.0/tools/components.py +40 -0
- exp_runtime-0.5.0/tools/package_desktop.py +166 -0
- exp_runtime-0.5.0/tools/package_ios.py +119 -0
- exp_runtime-0.5.0/tools/test_ios.py +224 -0
- exp_runtime-0.5.0/tools/test_packages.py +206 -0
- exp_runtime-0.5.0/uv.lock +406 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
name: Builds
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: ['**']
|
|
6
|
+
tags: ['v*']
|
|
7
|
+
pull_request:
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: desktop-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
15
|
+
cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
packages:
|
|
19
|
+
name: Python wheels (${{ matrix.python }})
|
|
20
|
+
runs-on: ubuntu-22.04
|
|
21
|
+
timeout-minutes: 15
|
|
22
|
+
strategy:
|
|
23
|
+
fail-fast: false
|
|
24
|
+
matrix:
|
|
25
|
+
python: ['3.10', '3.14']
|
|
26
|
+
steps:
|
|
27
|
+
- name: Check out source
|
|
28
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
29
|
+
with:
|
|
30
|
+
persist-credentials: false
|
|
31
|
+
|
|
32
|
+
- name: Install uv and select Python
|
|
33
|
+
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
|
|
34
|
+
with:
|
|
35
|
+
version: '0.12.13'
|
|
36
|
+
python-version: ${{ matrix.python }}
|
|
37
|
+
enable-cache: true
|
|
38
|
+
cache-suffix: python-${{ matrix.python }}
|
|
39
|
+
|
|
40
|
+
- name: Install locked build dependencies
|
|
41
|
+
run: uv sync --locked --extra build
|
|
42
|
+
|
|
43
|
+
- name: Build and audit wheels and source archives
|
|
44
|
+
shell: bash
|
|
45
|
+
run: |
|
|
46
|
+
flags=()
|
|
47
|
+
if [[ "$GITHUB_REF_TYPE" == tag ]]; then
|
|
48
|
+
flags+=(--tag "$GITHUB_REF_NAME")
|
|
49
|
+
fi
|
|
50
|
+
uv run --locked --extra build python tools/build_packages.py "${flags[@]}"
|
|
51
|
+
|
|
52
|
+
- name: Verify isolated pip installs and component removal
|
|
53
|
+
run: uv run --locked --extra build python tools/test_packages.py
|
|
54
|
+
|
|
55
|
+
- name: Upload Python distributions and checksums
|
|
56
|
+
if: matrix.python == '3.14'
|
|
57
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
58
|
+
with:
|
|
59
|
+
name: python-packages
|
|
60
|
+
path: dist/packages/*
|
|
61
|
+
if-no-files-found: error
|
|
62
|
+
retention-days: 30
|
|
63
|
+
|
|
64
|
+
ios:
|
|
65
|
+
name: iOS
|
|
66
|
+
uses: ./.github/workflows/ios-builds.yml
|
|
67
|
+
|
|
68
|
+
build:
|
|
69
|
+
name: ${{ matrix.target }}
|
|
70
|
+
runs-on: ${{ matrix.runner }}
|
|
71
|
+
timeout-minutes: 30
|
|
72
|
+
strategy:
|
|
73
|
+
fail-fast: false
|
|
74
|
+
matrix:
|
|
75
|
+
include:
|
|
76
|
+
- target: windows-x64
|
|
77
|
+
runner: windows-2022
|
|
78
|
+
- target: linux-x64
|
|
79
|
+
runner: ubuntu-22.04
|
|
80
|
+
- target: macos-arm64
|
|
81
|
+
runner: macos-14
|
|
82
|
+
- target: macos-x64
|
|
83
|
+
runner: macos-15-intel
|
|
84
|
+
defaults:
|
|
85
|
+
run:
|
|
86
|
+
shell: bash
|
|
87
|
+
env:
|
|
88
|
+
SDL_VIDEODRIVER: dummy
|
|
89
|
+
SDL_AUDIODRIVER: dummy
|
|
90
|
+
PYGAME_HIDE_SUPPORT_PROMPT: '1'
|
|
91
|
+
EXP_TARGET: ${{ matrix.target }}
|
|
92
|
+
EXP_BUILD_LABEL: ${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || github.sha }}
|
|
93
|
+
steps:
|
|
94
|
+
- name: Check out source
|
|
95
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
96
|
+
with:
|
|
97
|
+
persist-credentials: false
|
|
98
|
+
|
|
99
|
+
- name: Install uv and select Python
|
|
100
|
+
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
|
|
101
|
+
with:
|
|
102
|
+
version: '0.12.13'
|
|
103
|
+
python-version: '3.14'
|
|
104
|
+
enable-cache: true
|
|
105
|
+
cache-suffix: ${{ matrix.target }}
|
|
106
|
+
|
|
107
|
+
- name: Install locked dependencies
|
|
108
|
+
run: uv sync --locked --extra build
|
|
109
|
+
|
|
110
|
+
- name: Identify native build image
|
|
111
|
+
if: runner.os != 'macOS'
|
|
112
|
+
id: rar-image
|
|
113
|
+
# The hosted image version covers compiler, SDK and CMake updates.
|
|
114
|
+
# If unavailable, skip caching and build normally.
|
|
115
|
+
run: echo "version=${ImageVersion:-}" >> "$GITHUB_OUTPUT"
|
|
116
|
+
|
|
117
|
+
- name: Restore RAR decoder
|
|
118
|
+
if: runner.os != 'macOS' && steps.rar-image.outputs.version != ''
|
|
119
|
+
id: rar-cache
|
|
120
|
+
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
121
|
+
with:
|
|
122
|
+
path: |
|
|
123
|
+
build/rar/install
|
|
124
|
+
build/rar/libarchive-*.tar.xz
|
|
125
|
+
key: rar-v1-${{ matrix.runner }}-${{ runner.arch }}-${{ steps.rar-image.outputs.version }}-${{ hashFiles('tools/build_rar.py') }}
|
|
126
|
+
|
|
127
|
+
- name: Prepare RAR decoder
|
|
128
|
+
run: uv run --locked --extra build python tools/build_rar.py
|
|
129
|
+
|
|
130
|
+
# Persist a successful dependency build even if later tests fail.
|
|
131
|
+
- name: Save RAR decoder
|
|
132
|
+
if: steps.rar-cache.outputs.cache-primary-key != '' && steps.rar-cache.outputs.cache-hit != 'true'
|
|
133
|
+
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
134
|
+
with:
|
|
135
|
+
path: |
|
|
136
|
+
build/rar/install
|
|
137
|
+
build/rar/libarchive-*.tar.xz
|
|
138
|
+
key: ${{ steps.rar-cache.outputs.cache-primary-key }}
|
|
139
|
+
|
|
140
|
+
- name: Run tests without game content
|
|
141
|
+
run: uv run --locked --extra build python -m unittest discover -s tests
|
|
142
|
+
|
|
143
|
+
- name: Build desktop application
|
|
144
|
+
run: uv run --locked --extra build python tools/build_desktop.py
|
|
145
|
+
|
|
146
|
+
- name: Package, audit and test the extracted download
|
|
147
|
+
run: >-
|
|
148
|
+
uv run --locked --extra build python tools/package_desktop.py
|
|
149
|
+
--target "$EXP_TARGET" --label "$EXP_BUILD_LABEL" --smoke-test
|
|
150
|
+
|
|
151
|
+
- name: Upload downloadable archive and checksum
|
|
152
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
153
|
+
with:
|
|
154
|
+
name: desktop-${{ matrix.target }}
|
|
155
|
+
path: dist/downloads/*
|
|
156
|
+
if-no-files-found: error
|
|
157
|
+
compression-level: 0
|
|
158
|
+
retention-days: 30
|
|
159
|
+
|
|
160
|
+
publish-pypi:
|
|
161
|
+
name: Publish Python distributions to PyPI
|
|
162
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
|
163
|
+
needs: [build, ios, packages]
|
|
164
|
+
runs-on: ubuntu-22.04
|
|
165
|
+
timeout-minutes: 10
|
|
166
|
+
environment:
|
|
167
|
+
name: pypi
|
|
168
|
+
url: https://pypi.org/p/exp-runtime
|
|
169
|
+
permissions:
|
|
170
|
+
id-token: write
|
|
171
|
+
env:
|
|
172
|
+
EXP_TAG: ${{ github.ref_name }}
|
|
173
|
+
steps:
|
|
174
|
+
# Reuse the audited artifacts; do not build or install project code in
|
|
175
|
+
# the job that can request PyPI credentials.
|
|
176
|
+
- name: Download tested Python distributions and checksums
|
|
177
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
|
178
|
+
with:
|
|
179
|
+
name: python-packages
|
|
180
|
+
path: dist/packages
|
|
181
|
+
|
|
182
|
+
- name: Verify checksums and stage only publishable distributions
|
|
183
|
+
working-directory: dist/packages
|
|
184
|
+
shell: bash
|
|
185
|
+
run: |
|
|
186
|
+
version="${EXP_TAG#v}"
|
|
187
|
+
mkdir ../pypi
|
|
188
|
+
for name in exp_runtime exp_runtime_formats exp_runtime_engine exp_runtime_player exp_runtime_shs exp_runtime_cod; do
|
|
189
|
+
for suffix in -py3-none-any.whl .tar.gz; do
|
|
190
|
+
file="$name-$version$suffix"
|
|
191
|
+
sha256sum --check --strict "$file.sha256"
|
|
192
|
+
cp -- "$file" ../pypi/
|
|
193
|
+
done
|
|
194
|
+
done
|
|
195
|
+
|
|
196
|
+
- name: Publish wheels and source archives with Trusted Publishing
|
|
197
|
+
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
|
198
|
+
with:
|
|
199
|
+
packages-dir: dist/pypi/
|
|
200
|
+
|
|
201
|
+
release:
|
|
202
|
+
name: Publish versioned downloads
|
|
203
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
|
204
|
+
needs: [build, ios, packages]
|
|
205
|
+
runs-on: ubuntu-22.04
|
|
206
|
+
timeout-minutes: 10
|
|
207
|
+
permissions:
|
|
208
|
+
contents: write
|
|
209
|
+
env:
|
|
210
|
+
EXP_TAG: ${{ github.ref_name }}
|
|
211
|
+
steps:
|
|
212
|
+
- name: Check out release notes
|
|
213
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
214
|
+
with:
|
|
215
|
+
persist-credentials: false
|
|
216
|
+
|
|
217
|
+
- name: Download desktop archives and checksums
|
|
218
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
|
219
|
+
with:
|
|
220
|
+
pattern: desktop-*
|
|
221
|
+
path: dist/release
|
|
222
|
+
merge-multiple: true
|
|
223
|
+
|
|
224
|
+
- name: Download unsigned IPA and checksum
|
|
225
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
|
226
|
+
with:
|
|
227
|
+
name: ios-arm64-unsigned
|
|
228
|
+
path: dist/release
|
|
229
|
+
|
|
230
|
+
- name: Verify downloaded checksums
|
|
231
|
+
working-directory: dist/release
|
|
232
|
+
shell: bash
|
|
233
|
+
run: |
|
|
234
|
+
for target in windows-x64.zip linux-x64.tar.gz macos-arm64.zip macos-x64.zip ios-arm64-unsigned.ipa; do
|
|
235
|
+
test -s "exp-runtime-$EXP_TAG-$target"
|
|
236
|
+
test -s "exp-runtime-$EXP_TAG-$target.sha256"
|
|
237
|
+
done
|
|
238
|
+
sha256sum --check ./*.sha256
|
|
239
|
+
|
|
240
|
+
- name: Create release or update its downloads
|
|
241
|
+
env:
|
|
242
|
+
GH_TOKEN: ${{ github.token }}
|
|
243
|
+
GH_REPO: ${{ github.repository }}
|
|
244
|
+
shell: bash
|
|
245
|
+
run: |
|
|
246
|
+
if draft=$(gh release view "$EXP_TAG" --repo "$GH_REPO" --json isDraft --jq .isDraft 2>/dev/null); then
|
|
247
|
+
gh release upload "$EXP_TAG" dist/release/* --repo "$GH_REPO" --clobber
|
|
248
|
+
if [[ "$draft" == true ]]; then
|
|
249
|
+
gh release edit "$EXP_TAG" --repo "$GH_REPO" --draft=false
|
|
250
|
+
fi
|
|
251
|
+
else
|
|
252
|
+
flags=()
|
|
253
|
+
if [[ "$EXP_TAG" == *-* ]]; then
|
|
254
|
+
flags+=(--prerelease)
|
|
255
|
+
fi
|
|
256
|
+
gh release create "$EXP_TAG" dist/release/* \
|
|
257
|
+
--repo "$GH_REPO" --verify-tag --title "EXP Runtime $EXP_TAG" \
|
|
258
|
+
--notes-file RELEASE.md "${flags[@]}"
|
|
259
|
+
fi
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
name: iOS builds
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_call:
|
|
5
|
+
workflow_dispatch:
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: ios-${{ github.workflow }}-${{ github.ref }}
|
|
12
|
+
cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
build:
|
|
16
|
+
name: Unsigned iPhone app
|
|
17
|
+
runs-on: macos-26
|
|
18
|
+
timeout-minutes: 30
|
|
19
|
+
env:
|
|
20
|
+
PYTHONDONTWRITEBYTECODE: '1'
|
|
21
|
+
SDL_VIDEODRIVER: dummy
|
|
22
|
+
SDL_AUDIODRIVER: dummy
|
|
23
|
+
PYGAME_HIDE_SUPPORT_PROMPT: '1'
|
|
24
|
+
EXP_BUILD_LABEL: ${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || github.sha }}
|
|
25
|
+
steps:
|
|
26
|
+
- name: Check out source
|
|
27
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
28
|
+
with:
|
|
29
|
+
persist-credentials: false
|
|
30
|
+
|
|
31
|
+
- name: Install uv and select Python
|
|
32
|
+
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
|
|
33
|
+
with:
|
|
34
|
+
version: '0.12.13'
|
|
35
|
+
python-version: '3.14'
|
|
36
|
+
enable-cache: true
|
|
37
|
+
cache-suffix: ios
|
|
38
|
+
|
|
39
|
+
- name: Install locked host dependencies
|
|
40
|
+
run: uv sync --locked --extra desktop
|
|
41
|
+
|
|
42
|
+
- name: Restore iOS dependencies
|
|
43
|
+
id: ios-dependencies-cache
|
|
44
|
+
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
45
|
+
with:
|
|
46
|
+
path: build/ios/dependencies
|
|
47
|
+
key: ios-deps-v1-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('ios/dependencies.json', 'tools/build_ios.py') }}
|
|
48
|
+
|
|
49
|
+
- name: Prepare iOS dependencies
|
|
50
|
+
run: |
|
|
51
|
+
uv run --locked --extra desktop python tools/build_ios.py --prepare --sdk iphonesimulator
|
|
52
|
+
uv run --locked --extra desktop python tools/build_ios.py --prepare --sdk iphoneos
|
|
53
|
+
|
|
54
|
+
# Cache both SDKs before tests or simulator boot can fail.
|
|
55
|
+
- name: Save iOS dependencies
|
|
56
|
+
if: steps.ios-dependencies-cache.outputs.cache-primary-key != '' && steps.ios-dependencies-cache.outputs.cache-hit != 'true'
|
|
57
|
+
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
58
|
+
with:
|
|
59
|
+
path: build/ios/dependencies
|
|
60
|
+
key: ${{ steps.ios-dependencies-cache.outputs.cache-primary-key }}
|
|
61
|
+
|
|
62
|
+
- name: Run authored engine and packaging tests
|
|
63
|
+
run: uv run --locked --extra desktop python -m unittest discover -s tests
|
|
64
|
+
|
|
65
|
+
- name: Build simulator app
|
|
66
|
+
run: uv run --locked --extra desktop python tools/build_ios.py --sdk iphonesimulator
|
|
67
|
+
|
|
68
|
+
- name: Verify shared engine and native presentation on iOS
|
|
69
|
+
run: uv run --locked --extra desktop python tools/test_ios.py --boot-timeout 600 --install-timeout 300
|
|
70
|
+
|
|
71
|
+
- name: Upload simulator failure diagnostics
|
|
72
|
+
if: failure()
|
|
73
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
74
|
+
with:
|
|
75
|
+
name: ios-simulator-diagnostics
|
|
76
|
+
path: build/ios/simulator-diagnostics/
|
|
77
|
+
if-no-files-found: warn
|
|
78
|
+
retention-days: 7
|
|
79
|
+
|
|
80
|
+
- name: Build unsigned device app
|
|
81
|
+
run: uv run --locked --extra desktop python tools/build_ios.py --sdk iphoneos
|
|
82
|
+
|
|
83
|
+
- name: Audit and package unsigned IPA
|
|
84
|
+
run: uv run --locked --extra desktop python tools/package_ios.py --label "$EXP_BUILD_LABEL"
|
|
85
|
+
|
|
86
|
+
- name: Upload unsigned IPA and checksum
|
|
87
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
88
|
+
with:
|
|
89
|
+
name: ios-arm64-unsigned
|
|
90
|
+
path: |
|
|
91
|
+
dist/downloads/*-ios-arm64-unsigned.ipa
|
|
92
|
+
dist/downloads/*-ios-arm64-unsigned.ipa.sha256
|
|
93
|
+
if-no-files-found: error
|
|
94
|
+
compression-level: 0
|
|
95
|
+
retention-days: 30
|
|
96
|
+
|
|
97
|
+
- name: Upload simulator verification report
|
|
98
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
99
|
+
with:
|
|
100
|
+
name: ios-simulator-verification
|
|
101
|
+
path: build/ios/verification-simulator.json
|
|
102
|
+
if-no-files-found: error
|
|
103
|
+
retention-days: 30
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Python environments, caches and generated packages.
|
|
2
|
+
.venv/
|
|
3
|
+
venv/
|
|
4
|
+
__pycache__/
|
|
5
|
+
*.py[cod]
|
|
6
|
+
*.egg-info/
|
|
7
|
+
.pytest_cache/
|
|
8
|
+
.ruff_cache/
|
|
9
|
+
.mypy_cache/
|
|
10
|
+
.coverage*
|
|
11
|
+
htmlcov/
|
|
12
|
+
build/
|
|
13
|
+
dist/
|
|
14
|
+
*.spec
|
|
15
|
+
|
|
16
|
+
# User-provided game files and imported content.
|
|
17
|
+
*.[aA][pP][kK]
|
|
18
|
+
*.[iI][pP][aA]
|
|
19
|
+
*.[eE][xX][pP]
|
|
20
|
+
*.[zZ][iI][pP]
|
|
21
|
+
*.[rR][aA][rR]
|
|
22
|
+
*.[kK][iI][wW]
|
|
23
|
+
*.[sS][aA][vV]
|
|
24
|
+
*.shs-save.json
|
|
25
|
+
*.shs-auto.json
|
|
26
|
+
.shs-library/
|
|
27
|
+
.shs-import-*/
|
|
28
|
+
.exp-import-*/
|
|
29
|
+
.exp-library/
|
|
30
|
+
/library/
|
|
31
|
+
/Episodes/
|
|
32
|
+
/extract/
|
|
33
|
+
/game-assets/
|
|
34
|
+
/converted_assets/
|
|
35
|
+
/debug_images/
|
|
36
|
+
/original-screenshots/
|
|
37
|
+
/output/
|
|
38
|
+
/renpy-*-sdk/
|
|
39
|
+
/decomp/
|
|
40
|
+
|
|
41
|
+
# Private native research and generated reports.
|
|
42
|
+
*.so
|
|
43
|
+
*.dylib
|
|
44
|
+
*.dll
|
|
45
|
+
*.gpr
|
|
46
|
+
*.rep/
|
|
47
|
+
*.gzf
|
|
48
|
+
/docs/native-*
|
|
49
|
+
/docs/*-audit.json
|
|
50
|
+
/docs/*-trace.json
|
|
51
|
+
/local-reports/
|
|
52
|
+
*.log
|
|
53
|
+
|
|
54
|
+
# Editor and machine-local state.
|
|
55
|
+
.DS_Store
|
|
56
|
+
.idea/
|
|
57
|
+
.vscode/
|
|
58
|
+
xcuserdata/
|
|
59
|
+
*.xcuserstate
|
|
60
|
+
DerivedData/
|
|
61
|
+
*.xcarchive/
|
|
62
|
+
/ios/Signing.local.xcconfig
|
|
63
|
+
*.p12
|
|
64
|
+
*.p8
|
|
65
|
+
*.mobileprovision
|
|
66
|
+
*.provisionprofile
|
|
67
|
+
.env
|
|
68
|
+
.env.*
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# EXP Runtime
|
|
2
|
+
|
|
3
|
+
This is an experimental compatible engine for Surviving High School and Cause
|
|
4
|
+
of Death. Users supply SHS Android 1.0.9 APK / SHS IPA or CoD IPA assets and
|
|
5
|
+
additional EXP episodes. `exp_runtime` executes
|
|
6
|
+
original KiWi bytecode and renders user-supplied resources. It is not a static
|
|
7
|
+
ARM recompilation or a Ren'Py conversion.
|
|
8
|
+
|
|
9
|
+
## Build and verify
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
uv sync --locked --extra desktop
|
|
13
|
+
uv run --locked --extra desktop python -m unittest discover -s tests
|
|
14
|
+
uv run --locked --extra desktop exp-runtime
|
|
15
|
+
uv run --locked --extra build python tools/build_desktop.py
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Tests use authored fixtures. Optional original-content checks skip when a
|
|
19
|
+
player's local content is absent. Do not add original assets as test fixtures.
|
|
20
|
+
|
|
21
|
+
## Architecture and contracts
|
|
22
|
+
|
|
23
|
+
One uv workspace produces the `exp-runtime` umbrella and five component wheels.
|
|
24
|
+
Source lives under `packages/{formats,engine,player,shs,cod}/src/exp_runtime`.
|
|
25
|
+
Keep the shared `exp_runtime` namespace free of a root `__init__.py`, and give
|
|
26
|
+
each source file one wheel owner. `tools/build_packages.py` audits the wheels;
|
|
27
|
+
`tools/test_packages.py` checks isolated pip installs. See docs/SDK.md.
|
|
28
|
+
|
|
29
|
+
- `shs/`, `cod/`: game-specific import, asset/audio bindings and host services.
|
|
30
|
+
- `content.py`: validated EXP/APK/IPA import, exact resource IDs, relocatable
|
|
31
|
+
per-game libraries and separation of base versus episode resource banks.
|
|
32
|
+
- `decode/bytecode.py`, `vm.py`: lossless KiWi representation and real VM
|
|
33
|
+
execution, including pending argument frames and callbacks.
|
|
34
|
+
- `engine.py`, `runtime.py`: host services, panel state, clocks, choices,
|
|
35
|
+
mini games and versioned JSON saves.
|
|
36
|
+
- `application.py`, `desktop*.py`: shared launcher, menu, rendering and input.
|
|
37
|
+
- `graphics.py`, `platforms/`, `ios/`: pygame/native drawing primitives and the
|
|
38
|
+
Swift iOS host; keep game layout and behavior in the shared Python code.
|
|
39
|
+
- `fonts.py`, `ui_assets.py`, `atlas.py`: native asset and layout contracts.
|
|
40
|
+
|
|
41
|
+
Follow SCHEMA.md, VM_SPEC.md and docs/ENGINE_ABI.md. Unknown services must
|
|
42
|
+
remain explicit stops with their pending arguments intact. Never invent a
|
|
43
|
+
score, result, scene link or random value to bypass them. The heuristic AST
|
|
44
|
+
parser and Ren'Py experiments belong to the original research project.
|
|
45
|
+
|
|
46
|
+
Preserve the 1:1 target: original positions, font metrics, portrait masking,
|
|
47
|
+
pagination, panel lifecycle, input gates, timers, randomness and script-visible
|
|
48
|
+
side effects. Recover behavior and presentation together. Use Android 1.0.9
|
|
49
|
+
as the available reference for the reported identical iOS/Android interface.
|
|
50
|
+
The owner selected v0.1.3's SHS skin as the common presentation reference,
|
|
51
|
+
then supplied original screenshots and requested native verification of the
|
|
52
|
+
general title fix. Keep a common dialogue renderer; adapters supply each
|
|
53
|
+
game’s assets and native font metrics. Do not introduce a separate IPA layout.
|
|
54
|
+
The owner subsequently selected the verified iOS dialogue-box opening
|
|
55
|
+
animation for both games/platforms (120 ms travel, then 200 ms expansion).
|
|
56
|
+
This overrides Android's immediate box display; retain the common final
|
|
57
|
+
geometry. See docs/UI_FIDELITY.md for recovered paths and remaining limits.
|
|
58
|
+
Ghidra confirms that both iOS games wrap names at the native region width,
|
|
59
|
+
select a normal/tall header, and keep ordinary body text in its own region.
|
|
60
|
+
Honor those outline-font rules and Android's distinct bitmap-label rules.
|
|
61
|
+
Long titles may straddle the box border: do not force every name wholly above
|
|
62
|
+
it into the normal-height header. Bound fallback ink against the selected
|
|
63
|
+
header, skin, body and portrait; keep the drawing fit separate from saved
|
|
64
|
+
font history. Resolve text colors per game. See docs/IPA.md for evidence.
|
|
65
|
+
For other CoD-specific differences use its
|
|
66
|
+
supplied iOS native reference and docs/COD.md.
|
|
67
|
+
Keep unverified details explicit in the specifications.
|
|
68
|
+
|
|
69
|
+
Do not bundle APKs, EXPs, extracted art/audio/fonts/scripts, native
|
|
70
|
+
decompilations, screenshots, generated games, player libraries or saves.
|
|
71
|
+
Keep MANIFEST.in and package discovery restrictive. Preserve the inherited
|
|
72
|
+
MIT license and attribution in docs/PROVENANCE.md.
|
|
73
|
+
|
|
74
|
+
The owner handles Git initialization, commits, remotes and pushes. Creating
|
|
75
|
+
this directory does not authorize publishing it.
|