@next2d/builder 0.1.4 → 0.1.6

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.
Files changed (55) hide show
  1. package/README.md +11 -0
  2. package/dist/index.js +247 -3
  3. package/package.json +11 -9
  4. package/templates/xbox/CMakeLists.txt +121 -0
  5. package/templates/xbox/MicrosoftGame.config +36 -0
  6. package/templates/xbox/README.md +319 -0
  7. package/templates/xbox/cmake/FetchDawn.cmake +42 -0
  8. package/templates/xbox/cmake/FindV8.cmake +62 -0
  9. package/templates/xbox/js/bootstrap.js +143 -0
  10. package/templates/xbox/js/selftest.js +515 -0
  11. package/templates/xbox/src/AssetLoader.cpp +106 -0
  12. package/templates/xbox/src/AssetLoader.h +35 -0
  13. package/templates/xbox/src/EventLoop.cpp +162 -0
  14. package/templates/xbox/src/EventLoop.h +73 -0
  15. package/templates/xbox/src/HostContext.h +58 -0
  16. package/templates/xbox/src/bindings/Audio.cpp +320 -0
  17. package/templates/xbox/src/bindings/Bindings.h +75 -0
  18. package/templates/xbox/src/bindings/Canvas.cpp +171 -0
  19. package/templates/xbox/src/bindings/Canvas2D.cpp +462 -0
  20. package/templates/xbox/src/bindings/Console.cpp +52 -0
  21. package/templates/xbox/src/bindings/DomShims.cpp +221 -0
  22. package/templates/xbox/src/bindings/EventTarget.cpp +127 -0
  23. package/templates/xbox/src/bindings/EventTarget.h +17 -0
  24. package/templates/xbox/src/bindings/Fetch.cpp +149 -0
  25. package/templates/xbox/src/bindings/Gamepad.cpp +79 -0
  26. package/templates/xbox/src/bindings/Image.cpp +160 -0
  27. package/templates/xbox/src/bindings/ImageSource.h +26 -0
  28. package/templates/xbox/src/bindings/Network.cpp +303 -0
  29. package/templates/xbox/src/bindings/RasterCore.h +265 -0
  30. package/templates/xbox/src/bindings/Timers.cpp +87 -0
  31. package/templates/xbox/src/bindings/Video.cpp +235 -0
  32. package/templates/xbox/src/bindings/webgpu/WebGPU.cpp +1318 -0
  33. package/templates/xbox/src/bindings/webgpu/WebGPUCommon.h +119 -0
  34. package/templates/xbox/src/bindings/webgpu/WebGPUEnums.h +245 -0
  35. package/templates/xbox/src/gpu/DawnContext.cpp +170 -0
  36. package/templates/xbox/src/gpu/DawnContext.h +64 -0
  37. package/templates/xbox/src/main.cpp +368 -0
  38. package/templates/xbox/src/platform/AudioEngine.cpp +184 -0
  39. package/templates/xbox/src/platform/AudioEngine.h +65 -0
  40. package/templates/xbox/src/platform/GamepadManager.cpp +83 -0
  41. package/templates/xbox/src/platform/GamepadManager.h +40 -0
  42. package/templates/xbox/src/platform/ImageTypes.h +17 -0
  43. package/templates/xbox/src/platform/TextRasterizer.cpp +183 -0
  44. package/templates/xbox/src/platform/TextRasterizer.h +35 -0
  45. package/templates/xbox/src/platform/WicDecoder.cpp +63 -0
  46. package/templates/xbox/src/platform/WicDecoder.h +16 -0
  47. package/templates/xbox/src/v8/V8Runtime.cpp +284 -0
  48. package/templates/xbox/src/v8/V8Runtime.h +68 -0
  49. package/templates/xbox/src/v8/V8Util.h +56 -0
  50. package/templates/xbox/src/worker/WorkerRuntime.cpp +453 -0
  51. package/templates/xbox/src/worker/WorkerRuntime.h +108 -0
  52. package/templates/xbox/tests/check_local.sh +56 -0
  53. package/templates/xbox/tests/raster_test.bin +0 -0
  54. package/templates/xbox/tests/raster_test.cpp +279 -0
  55. package/templates/xbox/tests/windows_platform_test.cpp +187 -0
@@ -0,0 +1,319 @@
1
+ Next2D Xbox Host (GDK native / V8 + Dawn WebGPU)
2
+ ================================================
3
+
4
+ このディレクトリは `@next2d/builder --platform xbox` が生成する **Xbox GDK ネイティブタイトル** の
5
+ ホストプロジェクトです。Next2D の JavaScript を **V8** で実行し、描画を **Dawn(WebGPU → D3D12)** で行う
6
+ C++ 実行ファイルをビルドします。Electron や WebView は使用しません。
7
+
8
+ > **重要 / 検証ステータス**
9
+ > 本テンプレートは *アーキテクチャ的に整合したフルスキャフォールド* です。Xbox GDK タイトルの
10
+ > コンパイル・実機動作確認には **Windows + Visual Studio 2022 + Microsoft GDK + 開発機(devkit)** が
11
+ > 必須で、macOS/Linux では検証できません。GDK/実機が揃った段階で、下記「実機検証で残る作業」に沿って
12
+ > 最終調整(WebGPU バインディングの Next2D レンダラ実使用箇所への追従、画像アップロード経路、
13
+ > ストア設定値)を行ってください。
14
+
15
+ ---
16
+
17
+ ## アーキテクチャ
18
+
19
+ ```
20
+ ┌──────────────────────────────────────────────────────────────┐
21
+ │ Next2D アプリ (assets/app/*.js ← builder が vite build で生成) │
22
+ │ WebGPU / Canvas / rAF / fetch / Gamepad / WebAudio を使用 │
23
+ └───────────────▲──────────────────────────────────────────────┘
24
+ │ グローバル(navigator.gpu, requestAnimationFrame, ...)
25
+ ┌───────────────┴──────────────────────────────────────────────┐
26
+ │ js/bootstrap.js TextEncoder/TextDecoder/URL 等の JS 層補完 │
27
+ └───────────────▲──────────────────────────────────────────────┘
28
+ │ V8 バインディング (src/bindings/*)
29
+ ┌───────────────┴──────────────────────────────────────────────┐
30
+ │ C++ ホスト (src/) │
31
+ │ ├─ v8/V8Runtime Isolate/Context/ESM/マイクロタスク │
32
+ │ ├─ EventLoop setTimeout/rAF/performance.now │
33
+ │ ├─ bindings/ console/timers/fetch/Image/Audio/ │
34
+ │ │ WebGPU(navigator.gpu)/Gamepad/DOM │
35
+ │ ├─ gpu/DawnContext Instance/Adapter/Device/Surface(D3D12) │
36
+ │ ├─ platform/GamepadManager GameInput → W3C Gamepad │
37
+ │ ├─ platform/AudioEngine XAudio2 + Media Foundation デコード │
38
+ │ └─ main.cpp GDK 初期化 / ウィンドウ / ゲームループ │
39
+ └──────────────────────────────────────────────────────────────┘
40
+ ```
41
+
42
+ ゲームループ(`main.cpp`)は毎フレーム:
43
+ 1. Win32 メッセージ処理
44
+ 2. ゲームパッド入力ポーリング(GameInput)
45
+ 3. メインの タイマー実行 → マイクロタスク
46
+ 4. メインの `requestAnimationFrame`(アプリのロジック/描画コマンド生成)
47
+ 5. **Worker のメッセージ配送 + rAF**(レンダラ worker がここで WebGPU コマンドを submit)
48
+ 6. V8 プラットフォームタスク + Dawn `ProcessEvents`
49
+ 7. サーフェス Present
50
+
51
+ ### ランタイム環境の要点
52
+
53
+ - **jitless V8**: Xbox/Switch のリテールは JIT(動的コード生成)を禁止するため、V8 は
54
+ `--jitless`(Ignition インタプリタのみ)で起動する。WebAssembly も無効。
55
+ - **Worker / OffscreenCanvas**: player はレンダラを Worker + `transferControlToOffscreen`
56
+ で動かす。本ホストは **「同一 Isolate 内の別 Context を協調スケジューリングする単一スレッド
57
+ Worker モデル」** を採用(`src/worker/WorkerRuntime`)。`postMessage` は V8 の
58
+ ValueSerializer による structured clone、OffscreenCanvas は transfer 対応。GPU を 1 スレッドに
59
+ 保てるため Dawn のスレッド安全性問題を避けられる。真のマルチスレッド化は将来の最適化。
60
+ - **Canvas 2D**: `src/bindings/Canvas2D.cpp` にソフトウェア実装。パス/変換/`isPointInPath`
61
+ (ヒット判定の中核)・`fill`/`stroke`・`getImageData` を実装。実グリフ描画(`fillText` の見た目)は
62
+ 未実装(`measureText` は近似メトリクス)。
63
+ - **グラフィックスバックエンド抽象化**: `HostContext::backend`(WebGPU/WebGL2)で切替。Xbox は
64
+ WebGPU。`navigator.gpu` はバックエンドが WebGPU のときのみ公開し、WebGL2(Switch)では
65
+ player が `canvas.getContext('webgl2')` へ自動フォールバックする。canvas の getContext は
66
+ `src/bindings/Canvas.cpp` が backend に応じて `2d`/`webgpu`/`webgl2` をディスパッチ。
67
+
68
+ ---
69
+
70
+ ## 必要環境
71
+
72
+ | 項目 | 内容 |
73
+ |------|------|
74
+ | OS | Windows 11 |
75
+ | IDE | Visual Studio 2022 (v143, C++ Game development workload) |
76
+ | GDK | Microsoft GDK (June 2024 以降) — ID@Xbox 登録が必要 |
77
+ | CMake | 3.26 以降 |
78
+ | V8 | prebuilt monolith (`v8_monolith.lib` + `include/`) |
79
+ | Dawn | CMake の FetchContent で自動取得(ネットワーク必須) |
80
+ | devkit | Xbox 開発機(実機検証用) |
81
+
82
+ ---
83
+
84
+ ## V8 の用意
85
+
86
+ V8 はソースビルドが非常に重いため prebuilt monolith を使います。自前ビルド例:
87
+
88
+ ```bat
89
+ :: depot_tools 導入後
90
+ fetch v8
91
+ cd v8
92
+ gn gen out\x64.release --args="v8_monolithic=true v8_use_external_startup_data=false is_component_build=false target_cpu=\"x64\" is_debug=false v8_enable_pointer_compression=true v8_enable_sandbox=true"
93
+ ninja -C out\x64.release v8_monolith
94
+ ```
95
+
96
+ 生成物を次の構成で配置し、builder の `--v8-root` 引数 (または環境変数 `V8_ROOT`) で指すこと:
97
+
98
+ ```
99
+ <V8_ROOT>/include/v8.h ...
100
+ <V8_ROOT>/lib/v8_monolith.lib
101
+ ```
102
+
103
+ > V8 のビルドフラグ(pointer compression / sandbox)は `CMakeLists.txt` の
104
+ > `V8_COMPRESS_POINTERS` / `V8_ENABLE_SANDBOX` と一致させてください。不一致は ABI 崩れの原因になります。
105
+
106
+ ---
107
+
108
+ ## ビルド手順
109
+
110
+ builder 経由(推奨):
111
+
112
+ ```bat
113
+ :: プロジェクトルートで。V8 は --v8-root で指定する (環境変数 V8_ROOT でも可)
114
+ npx @next2d/builder --platform xbox --env prd --v8-root C:\path\to\v8
115
+ ```
116
+
117
+ builder は次を行います:
118
+ 1. Web 資材を `vite build` で生成
119
+ 2. `xbox/assets/app` へ資材を配置
120
+ 3. CMake で GDK 構成(`-A Gaming.Xbox.Scarlett.x64`)を生成
121
+ 4. `cmake --build`(Release)でパッケージ生成
122
+
123
+ 対象世代を変える場合は環境変数 `NEXT2D_XBOX_ARCH` を設定:
124
+ `Gaming.Xbox.Scarlett.x64`(既定) / `Gaming.Xbox.XboxOne.x64` / `Gaming.Desktop.x64`
125
+
126
+ Visual Studio で開いて実行/デバッグ:
127
+
128
+ ```bat
129
+ npx @next2d/builder --platform xbox --env prd --open
130
+ ```
131
+
132
+ CMake を直接叩く場合:
133
+
134
+ ```bat
135
+ cmake -S xbox -B out/xbox/build -G "Visual Studio 17 2022" -A Gaming.Xbox.Scarlett.x64 -D V8_ROOT=%V8_ROOT%
136
+ cmake --build out/xbox/build --config Release
137
+ ```
138
+
139
+ ---
140
+
141
+ ## テスト
142
+
143
+ Windows / GDK が無い環境でも検証できるよう、テストは 3 層に分かれています。
144
+
145
+ > 1・2 は **builder リポジトリ (Next2D/builder) 側**の開発用テストで、ゲーム側の
146
+ > `xbox/` にはコピーされません (`tests/` はスキャフォールド対象外)。
147
+ > ゲーム側で実行するのは 3 のセルフテストのみです。
148
+
149
+ ### 1. どこでも実行できる単体テスト (`tests/raster_test.cpp`)
150
+
151
+ Canvas2D のソフトラスタライザ純ロジック (`src/bindings/RasterCore.h` —
152
+ 塗り/winding/クリップ/色解析/曲線フラット化) は V8/Windows 非依存で、
153
+ macOS / Linux でそのまま実行できます:
154
+
155
+ ```bash
156
+ # raster テスト + ASan + V8 ヘッダに対する構文チェックを一括実行
157
+ tests/check_local.sh
158
+ ```
159
+
160
+ 構文チェックは実 V8 ヘッダ (pin: `13.6.233.17`) に対して、Windows API 非依存の
161
+ V8 バインディング 12 ファイルをコンパイル検証します (API 削除・型不整合を検出)。
162
+
163
+ ### 2. GitHub Actions (windows-latest) — `.github/workflows/xbox-host-ci.yml`
164
+
165
+ ローカルに Windows が無くても、push すると CI が Windows 上で実行します:
166
+
167
+ - **RasterCore 単体テスト** を MSVC でビルド・実行 (Linux では gcc + ASan/UBSan でも)
168
+ - **Windows 実 API smoke テスト** (`tests/windows_platform_test.cpp`):
169
+ WIC の PNG デコード、DirectWrite/Direct2D のグリフラスタライズ (英/日)、
170
+ Media Foundation の音声デコード、XAudio2 初期化 — を実際に実行して検証
171
+ - **V8 依存ソースのコンパイル検証** (V8 ヘッダ + MSVC、リンクなし)
172
+
173
+ CI 対象外 (実機セットアップ時に検証): Dawn 依存の `WebGPU.cpp` / `DawnContext.cpp` /
174
+ `main.cpp` (webgpu_cpp.h が Dawn ビルドで生成されるため) と GDK 依存の `GamepadManager.cpp`。
175
+
176
+ ### 3. 実機セルフテスト (`js/selftest.js`)
177
+
178
+ ビルドが通ったら最初に実行するテスト。アプリの代わりに全バインディングを
179
+ 実機/PC 上で網羅実行し、TAP 形式で結果を出して自動終了します:
180
+
181
+ ```bat
182
+ Next2DXboxHost.exe --selftest
183
+ ```
184
+
185
+ 検証内容: タイマー/rAF/イベント、WIC 画像デコード、Canvas2D (fill/clip/
186
+ isPointInPath/fillText/drawImage)、Blob/URL/XHR、Worker (blob URL +
187
+ structured clone + OffscreenCanvas 転送)、**WebGPU 実行経路** (バッファ読み戻し、
188
+ copyExternalImageToTexture、**dynamic offset 付き描画**、**stencil8 マスク描画**)、
189
+ 音声 (decodeAudioData/gain/ended)、ゲームパッド、クリップボード。
190
+ 終了コード 0 = 全パス。
191
+
192
+ ---
193
+
194
+ ## WebGPU バインディングの実装範囲
195
+
196
+ `src/bindings/webgpu/` は **Next2D の WebGPU レンダラが使用するコア経路** を実装しています:
197
+
198
+ - `navigator.gpu` : `requestAdapter` / `getPreferredCanvasFormat`
199
+ - `GPUAdapter` : `requestDevice`
200
+ - `GPUDevice` : `createBuffer` / `createTexture` / `createSampler` / `createShaderModule` /
201
+ `createBindGroupLayout` / `createBindGroup` / `createPipelineLayout` /
202
+ `createRenderPipeline` / `createCommandEncoder` / `queue` / `limits`
203
+ - `GPUQueue` : `submit` / `writeBuffer` / `writeTexture` / `copyExternalImageToTexture`
204
+ (画像/テキスト/動画のテクスチャ化。CPUで flipY/premultiply を適用し WriteTexture へ)
205
+ - `GPUCommandEncoder` : `beginRenderPass` / `finish` / `copyBufferToBuffer` /
206
+ `copyTextureToTexture` / `copyTextureToBuffer`(ピクセル読み戻し)
207
+ - `GPURenderPassEncoder` : `setPipeline` / `setBindGroup`(**dynamic offsets 対応**) /
208
+ `setVertexBuffer` / `setIndexBuffer` / `setViewport` / `setScissorRect` /
209
+ `setStencilReference`(**マスク処理**) / `setBlendConstant` / `draw` / `drawIndexed` /
210
+ `drawIndirect`(コンテナ一括描画) / `end`
211
+ - ステンシル: `depthStencil`(`stencilFront`/`stencilBack`/`stencilReadMask`/`stencilWriteMask`、
212
+ `stencil8` フォーマット)と `depthStencilAttachment`(`stencilLoadOp`/`stencilStoreOp`/
213
+ `stencilClearValue`)を解析。Next2D のマスク/クリップ描画の中核。
214
+ - `GPUBuffer` : `getMappedRange` / `mapAsync`(READ) / `unmap` / `destroy`
215
+ - `GPUTexture` : `createView` / `destroy`
216
+ - `canvas.getContext('webgpu')` : `configure` / `getCurrentTexture`
217
+
218
+ > player(`@next2d/player`) の実 API 使用を突合済み。**コンピュートシェーダ / render bundle /
219
+ > indexed draw / importExternalTexture は player が未使用**のため未実装で問題なし。
220
+ - 定数: `GPUBufferUsage` / `GPUTextureUsage` / `GPUShaderStage` / `GPUColorWrite` / `GPUMapMode`
221
+
222
+ WebGPU IDL は約 40 型・数百メソッドあり、全面手書きは現実的でないため、上記コアを実装し
223
+ 拡張ポイントを `«EXTEND»` コメントで明示しています。追加が必要になった API は同じラップ
224
+ パターン(`WrapWith` / `Unwrap` / ディスクリプタ解析ヘルパー)で追記してください。
225
+
226
+ ---
227
+
228
+ ## Next2D 機能カバレッジ (player 突合)
229
+
230
+ player の実 API 使用を全面調査し、以下を実装済み。**この環境(macOS/GDK・devkit 無)では
231
+ コンパイル・実機検証は不可**のため、下表は「コード上の対応状況」であり実機での見た目・挙動は
232
+ 別途検証が必要です。
233
+
234
+ | 機能 | 状態 | 備考 |
235
+ |------|------|------|
236
+ | WebGPU コア描画 (shape/mask/blend/pipeline) | ✅ 実装 | 初期化 limits も対応 |
237
+ | マスク/クリップ (ステンシル + `setStencilReference` + dynamic offset) | ✅ 実装 | `stencil8`/`stencilFront`/`stencilBack` を解析 |
238
+ | コンテナ一括描画 (`drawIndirect`) | ✅ 実装 | |
239
+ | 画像/テキスト/動画のテクスチャ化 (`copyExternalImageToTexture`) | ✅ 実装 | flipY/premultiply を CPU 適用 |
240
+ | フィルタ (`copyTextureToTexture` + fragment shader) | ✅ 実装 | コンピュート不使用のため対応可 |
241
+ | ピクセル読み戻し (`copyTextureToBuffer`+`mapAsync`) | ✅ 実装 | BitmapData/getPixels |
242
+ | ヒット判定 (Canvas2D `isPointInPath`) | ✅ 実装 | ソフトラスタ |
243
+ | **テキスト表示** (`fillText`/`measureText`/`clip`) | ⚠️ 実装(要検証) | DirectWrite/Direct2D。`clip` は矩形近似(TextField 枠に十分)。ベースライン/合字/絵文字は実機検証 |
244
+ | アセット読込 (`XMLHttpRequest`) | ✅ 実装 | assets/blob から同期読込 |
245
+ | Worker/OffscreenCanvas (レンダラ) | ✅ 実装(要検証) | 協調シングルスレッド + `?worker&inline`(blob) 対応 |
246
+ | `Blob`/`URL.createObjectURL`/`ImageData` | ✅ 実装 | |
247
+ | ゲームパッド入力 | ✅ 実装 | `navigator.getGamepads` ポーリング |
248
+ | サウンド (WebAudio 最小) | ⚠️ 実装(要検証) | decode/play/stop/音量/ミュート/`ended` 発火に対応。AnalyserNode 等は未対応 |
249
+ | ポインタ/キーボード/ホイール入力 | ⚠️ 実装(要検証) | `WndProc`→`DispatchEvent`。配送先canvasの特定は実機検証 |
250
+ | 動画 (HTMLVideoElement) | ⚠️ 実装(要検証) | `Video.cpp`(Media Foundation)。フレーム精度/音声同期は実機検証 |
251
+ | クリップボード (`navigator.clipboard`) | ✅ 実装 | Win32 クリップボード (readText/writeText) |
252
+
253
+ > player が使用する API はコード上すべて実装済み。残る唯一の障壁は
254
+ > **GDK/devkit を要するコンパイル・実機検証**(この環境では物理的に不可)。
255
+
256
+ ## 実機検証で残る作業
257
+
258
+ 0. **まずセルフテスト**: ビルドが通ったら `Next2DXboxHost.exe --selftest` を実行。
259
+ 全バインディングを一括検証し、失敗箇所が TAP 形式で列挙されます (上記「テスト」参照)。
260
+ 1. **Dawn / V8 API 追従**: `FetchDawn.cmake` の `DAWN_TAG` と V8 バージョンで
261
+ webgpu_cpp のシンボル名(例 `ShaderSourceWGSL` / `Limits` / `GetLimits` の戻り値型)が
262
+ 異なる場合があります。該当タグの `webgpu_cpp.h` に合わせて調整してください。
263
+ 2. **テキストの見た目**: `Canvas2D.cpp` の `fillText`/`measureText` は DirectWrite/Direct2D で
264
+ 実装済みですが、ベースライン位置・`textAlign`/`textBaseline`・合字/絵文字は実機で要検証。
265
+ 3. **ポインタ/キーボード入力**: `main.cpp` の `WndProc` でマウス/キー/ホイールを
266
+ `DispatchEvent` 経由で window/document/主要canvas へ配送済み。ただし player がリスナを
267
+ 登録する canvas インスタンスの特定はヒューリスティック(最後に生成した canvas)のため、
268
+ 実機で正しい配送先か検証・調整してください。キーボードは window 登録で信頼できます。
269
+ 4. **動画 (任意機能)**: `<video>`(HTMLVideoElement) は `Video.cpp`(Media Foundation)で
270
+ デコード/フレーム供給を実装済み。フレーム精度・音声同期は実機で要検証。
271
+ 5. **サウンド**: source→gain→destination の最小グラフ・音量・ミュート・`ended` 発火を
272
+ 実装済み(`Audio.cpp`)。再生タイミング/レイテンシは実機で要検証。AnalyserNode 等の
273
+ 高度なノードは未対応(player 未使用)。
274
+ 6. **Worker スクリプト形式**: `WorkerRuntime` はクラシック/blob worker を評価します。
275
+ ESM worker の場合は IIFE 出力設定にするか `WorkerInstance::Start` を module 評価へ拡張。
276
+ 7. **GameInput 複数台 / パフォーマンス(GC・present モード)**: 実機で調整。
277
+ 7. **MicrosoftGame.config**: **プロジェクトルート**で管理(capacitor.config.json と同じ)。
278
+ `TitleId`/`StoreId`/`MSAAppId` を Partner Center 値へ置換、ストアロゴ(`xbox/assets/*.png`)を用意。
279
+ 8. **jitless の性能**: JIT 無効化のオーバーヘッドは V8 スナップショット等で緩和を検討。
280
+
281
+ ## Nintendo Switch への展開
282
+
283
+ 本ホストは Switch 移植を見据えた構成です。共通コア(V8/Worker/入力/音声/Canvas2D/AssetLoader)は
284
+ そのまま流用でき、差分は主に以下:
285
+
286
+ - **JIT 禁止は Switch も同様** → jitless V8 の構成をそのまま使用。
287
+ - **グラフィックス**: Dawn に Switch(NVN) バックエンドは無いため、`HostContext::backend` を
288
+ `WebGL2` にして `canvas.getContext('webgl2')` を Switch の GL に実装する
289
+ (`Canvas.cpp` の `«SWITCH»`)。player は WebGL2 バックエンドを持つため描画コードは再利用できる。
290
+ - **SDK**: NintendoSDK は NDA 下で、承認 + devkit が必須。SDK 呼び出し箇所を埋めた
291
+ スキャフォールドとして拡張する。
292
+
293
+ ---
294
+
295
+ ## ディレクトリ構成
296
+
297
+ ```
298
+ xbox/
299
+ ├─ CMakeLists.txt GDK ビルド構成
300
+ ├─ MicrosoftGame.config GDK ゲーム設定 (要 ID@Xbox 値)
301
+ ├─ cmake/
302
+ │ ├─ FetchDawn.cmake Dawn 取得(D3D12 バックエンド)
303
+ │ └─ FindV8.cmake prebuilt V8 の探索
304
+ ├─ js/bootstrap.js JS 層のブラウザ相当補完
305
+ ├─ assets/app/ builder が Web 資材を配置
306
+ └─ src/
307
+ ├─ main.cpp
308
+ ├─ HostContext.h
309
+ ├─ AssetLoader.{h,cpp}
310
+ ├─ EventLoop.{h,cpp}
311
+ ├─ v8/{V8Runtime,V8Util}.*
312
+ ├─ gpu/DawnContext.{h,cpp}
313
+ ├─ platform/{GamepadManager,AudioEngine}.*
314
+ └─ bindings/
315
+ ├─ Bindings.h
316
+ ├─ Console.cpp Timers.cpp Fetch.cpp Image.cpp Audio.cpp
317
+ ├─ Gamepad.cpp DomShims.cpp
318
+ └─ webgpu/{WebGPU.cpp,WebGPUCommon.h,WebGPUEnums.h}
319
+ ```
@@ -0,0 +1,42 @@
1
+ # =============================================================================
2
+ # Dawn (Google WebGPU 実装) を取得してビルドする。
3
+ # D3D12 バックエンドのみを有効化し、Xbox(GDK)/PC(GDK) で利用する。
4
+ #
5
+ # 注意:
6
+ # - Dawn のビルドには depot_tools 由来の一部が不要になる CMake パスを使用する。
7
+ # - 初回構成はネットワークとビルド時間を要する。CI ではキャッシュ推奨。
8
+ # - DAWN_TAG は動作確認済みタグに固定すること (chromium ブランチに追従)。
9
+ # =============================================================================
10
+ include(FetchContent)
11
+
12
+ set(DAWN_TAG "chromium/6478" CACHE STRING "Dawn のチェックアウトタグ")
13
+
14
+ # Dawn のビルドオプション: 必要なものだけを有効化
15
+ set(DAWN_FETCH_DEPENDENCIES ON CACHE BOOL "" FORCE)
16
+ set(DAWN_ENABLE_D3D12 ON CACHE BOOL "" FORCE)
17
+ set(DAWN_ENABLE_D3D11 OFF CACHE BOOL "" FORCE)
18
+ set(DAWN_ENABLE_VULKAN OFF CACHE BOOL "" FORCE)
19
+ set(DAWN_ENABLE_METAL OFF CACHE BOOL "" FORCE)
20
+ set(DAWN_ENABLE_OPENGLES OFF CACHE BOOL "" FORCE)
21
+ set(DAWN_ENABLE_DESKTOP_GL OFF CACHE BOOL "" FORCE)
22
+ set(DAWN_ENABLE_NULL OFF CACHE BOOL "" FORCE)
23
+ set(DAWN_BUILD_SAMPLES OFF CACHE BOOL "" FORCE)
24
+ set(TINT_BUILD_TESTS OFF CACHE BOOL "" FORCE)
25
+ set(TINT_BUILD_CMD_TOOLS OFF CACHE BOOL "" FORCE)
26
+
27
+ # webgpu_dawn: webgpu.h C-API を提供する統合ライブラリ (バインディング層はこれを叩く)
28
+ set(DAWN_BUILD_MONOLITHIC_LIBRARY ON CACHE BOOL "" FORCE)
29
+
30
+ FetchContent_Declare(
31
+ dawn
32
+ GIT_REPOSITORY https://dawn.googlesource.com/dawn
33
+ GIT_TAG ${DAWN_TAG}
34
+ GIT_SHALLOW TRUE
35
+ )
36
+
37
+ FetchContent_MakeAvailable(dawn)
38
+
39
+ # webgpu_dawn ターゲットに dawn::webgpu_dawn エイリアスが無いバージョン向けの保険
40
+ if(NOT TARGET dawn::webgpu_dawn AND TARGET webgpu_dawn)
41
+ add_library(dawn::webgpu_dawn ALIAS webgpu_dawn)
42
+ endif()
@@ -0,0 +1,62 @@
1
+ # =============================================================================
2
+ # V8 (prebuilt monolith) を探して v8::v8 ターゲットを定義する。
3
+ #
4
+ # V8 は GN/depot_tools でのソースビルドが非常に重いため、prebuilt を前提とする。
5
+ # 以下のいずれかで monolith を用意すること:
6
+ #
7
+ # 1. 自前ビルド (推奨・再現性高)
8
+ # fetch v8 && cd v8
9
+ # gn gen out/x64.release --args='
10
+ # v8_monolithic=true
11
+ # v8_use_external_startup_data=false
12
+ # is_component_build=false
13
+ # target_cpu="x64"
14
+ # is_debug=false
15
+ # v8_enable_pointer_compression=true
16
+ # v8_enable_sandbox=true'
17
+ # ninja -C out/x64.release v8_monolith
18
+ #
19
+ # 2. 配布物 (v8_monolith.lib + include/) を取得
20
+ #
21
+ # cmake 構成時に -D V8_ROOT=<path> を渡す。
22
+ # <V8_ROOT>/include/v8.h
23
+ # <V8_ROOT>/lib/v8_monolith.lib
24
+ # =============================================================================
25
+ if(NOT DEFINED V8_ROOT)
26
+ set(V8_ROOT "$ENV{V8_ROOT}")
27
+ endif()
28
+
29
+ if(NOT V8_ROOT OR NOT EXISTS "${V8_ROOT}")
30
+ message(FATAL_ERROR
31
+ "V8_ROOT が未設定/不正です。prebuilt V8 monolith のパスを指定してください:\n"
32
+ " npx @next2d/builder --platform xbox --env prd --v8-root C:/path/to/v8\n"
33
+ " (CMake 直叩きの場合: cmake -D V8_ROOT=C:/path/to/v8 ...)\n"
34
+ "詳細は README.md の『V8 の用意』を参照。")
35
+ endif()
36
+
37
+ find_path(V8_INCLUDE_DIR
38
+ NAMES v8.h
39
+ PATHS "${V8_ROOT}/include"
40
+ NO_DEFAULT_PATH
41
+ )
42
+
43
+ find_library(V8_MONOLITH_LIB
44
+ NAMES v8_monolith
45
+ PATHS "${V8_ROOT}/lib" "${V8_ROOT}/out/x64.release/obj"
46
+ NO_DEFAULT_PATH
47
+ )
48
+
49
+ if(NOT V8_INCLUDE_DIR OR NOT V8_MONOLITH_LIB)
50
+ message(FATAL_ERROR "V8 の include / v8_monolith.lib が見つかりません (V8_ROOT=${V8_ROOT})")
51
+ endif()
52
+
53
+ add_library(v8::v8 STATIC IMPORTED)
54
+ set_target_properties(v8::v8 PROPERTIES
55
+ IMPORTED_LOCATION "${V8_MONOLITH_LIB}"
56
+ INTERFACE_INCLUDE_DIRECTORIES "${V8_INCLUDE_DIR}"
57
+ )
58
+
59
+ # V8 monolith が要求する Windows ライブラリ
60
+ target_link_libraries(v8::v8 INTERFACE winmm dbghelp)
61
+
62
+ message(STATUS "V8 found: ${V8_MONOLITH_LIB}")
@@ -0,0 +1,143 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Next2D Xbox host ブートストラップ。
5
+ *
6
+ * C++ ホスト(V8Runtime)が起動時にクラシックスクリプトとして最初に評価する。
7
+ * ここでは C++ バインディングが用意していないブラウザ相当 API を JS 層で補完し、
8
+ * Next2D アプリ本体(ESM)が正しく動く前提を整える。
9
+ *
10
+ * すでに C++ 側で用意済み:
11
+ * console / setTimeout / setInterval / requestAnimationFrame / performance.now /
12
+ * fetch / Image / createImageBitmap / AudioContext / navigator.gpu /
13
+ * navigator.getGamepads / window / document / screen / devicePixelRatio
14
+ */
15
+ (function (global) {
16
+
17
+ // --- queueMicrotask (V8 が未提供の場合の保険) ---------------------------
18
+ if (typeof global.queueMicrotask !== "function") {
19
+ global.queueMicrotask = function (callback) {
20
+ Promise.resolve().then(callback);
21
+ };
22
+ }
23
+
24
+ // --- TextEncoder / TextDecoder (UTF-8) ---------------------------------
25
+ // V8 単体には Web の Text* が含まれないため最小実装を提供する。
26
+ if (typeof global.TextEncoder === "undefined") {
27
+ global.TextEncoder = class TextEncoder {
28
+ get encoding() { return "utf-8"; }
29
+ encode(str) {
30
+ str = String(str);
31
+ const out = [];
32
+ for (let i = 0; i < str.length; i++) {
33
+ let code = str.charCodeAt(i);
34
+ if (code < 0x80) {
35
+ out.push(code);
36
+ } else if (code < 0x800) {
37
+ out.push(0xc0 | (code >> 6), 0x80 | (code & 0x3f));
38
+ } else if (code >= 0xd800 && code <= 0xdbff) {
39
+ // サロゲートペア
40
+ const hi = code;
41
+ const lo = str.charCodeAt(++i);
42
+ code = 0x10000 + ((hi - 0xd800) << 10) + (lo - 0xdc00);
43
+ out.push(
44
+ 0xf0 | (code >> 18),
45
+ 0x80 | ((code >> 12) & 0x3f),
46
+ 0x80 | ((code >> 6) & 0x3f),
47
+ 0x80 | (code & 0x3f)
48
+ );
49
+ } else {
50
+ out.push(
51
+ 0xe0 | (code >> 12),
52
+ 0x80 | ((code >> 6) & 0x3f),
53
+ 0x80 | (code & 0x3f)
54
+ );
55
+ }
56
+ }
57
+ return new Uint8Array(out);
58
+ }
59
+ };
60
+ }
61
+
62
+ if (typeof global.TextDecoder === "undefined") {
63
+ global.TextDecoder = class TextDecoder {
64
+ constructor(label) { this._label = label || "utf-8"; }
65
+ get encoding() { return "utf-8"; }
66
+ decode(input) {
67
+ if (!input) return "";
68
+ const bytes = input instanceof Uint8Array
69
+ ? input
70
+ : new Uint8Array(input.buffer || input);
71
+ let out = "";
72
+ let i = 0;
73
+ while (i < bytes.length) {
74
+ let c = bytes[i++];
75
+ if (c < 0x80) {
76
+ out += String.fromCharCode(c);
77
+ } else if (c < 0xe0) {
78
+ out += String.fromCharCode(((c & 0x1f) << 6) | (bytes[i++] & 0x3f));
79
+ } else if (c < 0xf0) {
80
+ out += String.fromCharCode(
81
+ ((c & 0x0f) << 12) | ((bytes[i++] & 0x3f) << 6) | (bytes[i++] & 0x3f)
82
+ );
83
+ } else {
84
+ let code = ((c & 0x07) << 18) | ((bytes[i++] & 0x3f) << 12) |
85
+ ((bytes[i++] & 0x3f) << 6) | (bytes[i++] & 0x3f);
86
+ code -= 0x10000;
87
+ out += String.fromCharCode(0xd800 + (code >> 10), 0xdc00 + (code & 0x3ff));
88
+ }
89
+ }
90
+ return out;
91
+ }
92
+ };
93
+ }
94
+
95
+ // --- URL の最小補完 -----------------------------------------------------
96
+ // ローカル実行では基本パスのみ扱えれば十分。標準 URL があればそれを使う。
97
+ if (typeof global.URL === "undefined") {
98
+ global.URL = class URL {
99
+ constructor(url, base) {
100
+ this.href = base ? (String(base).replace(/\/?$/, "/") + url) : String(url);
101
+ this.pathname = this.href.replace(/^[a-z]+:\/\/[^/]*/i, "");
102
+ this.search = "";
103
+ this.hash = "";
104
+ }
105
+ toString() { return this.href; }
106
+ };
107
+ global.URL.createObjectURL = function () { return ""; };
108
+ global.URL.revokeObjectURL = function () {};
109
+ }
110
+
111
+ // --- location (Next2D が参照する場合の最小値) ---------------------------
112
+ if (typeof global.location === "undefined") {
113
+ global.location = {
114
+ href: "app://local/",
115
+ origin: "app://local",
116
+ protocol: "app:",
117
+ host: "local",
118
+ hostname: "local",
119
+ pathname: "/",
120
+ search: "",
121
+ hash: "",
122
+ reload() {}
123
+ };
124
+ }
125
+
126
+ // --- 既定キャンバス -----------------------------------------------------
127
+ // Next2D は通常 document.body に canvas を追加するが、C++ 側で用意済みの
128
+ // メインキャンバスを既定として参照できるようにしておく。
129
+ if (global.document && global.document.__mainCanvas && !global.document.body.__hasCanvas) {
130
+ global.document.body.__hasCanvas = true;
131
+ }
132
+
133
+ // --- 未処理例外/Promise 拒否の可視化 -----------------------------------
134
+ global.addEventListener("error", function (e) {
135
+ console.error("[unhandled error]", e && e.message ? e.message : e);
136
+ });
137
+ global.addEventListener("unhandledrejection", function (e) {
138
+ console.error("[unhandled rejection]", e && e.reason ? e.reason : e);
139
+ });
140
+
141
+ console.log("[bootstrap] Next2D Xbox host environment ready.");
142
+
143
+ })(globalThis);