@next2d/builder 0.1.8 → 0.1.11
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.
- package/dist/cli.d.ts +59 -0
- package/dist/cli.js +141 -0
- package/dist/constants.d.ts +53 -0
- package/dist/constants.js +64 -0
- package/dist/context.d.ts +29 -0
- package/dist/context.js +19 -0
- package/dist/electron.d.ts +10 -0
- package/dist/electron.js +142 -0
- package/dist/index.js +18 -790
- package/dist/native.d.ts +27 -0
- package/dist/native.js +123 -0
- package/dist/utils.d.ts +27 -0
- package/dist/utils.js +40 -0
- package/dist/web.d.ts +18 -0
- package/dist/web.js +70 -0
- package/dist/xbox.d.ts +62 -0
- package/dist/xbox.js +426 -0
- package/package.json +11 -9
- package/templates/xbox/CMakeLists.txt +47 -11
- package/templates/xbox/README.md +18 -0
- package/templates/xbox/js/bootstrap.js +120 -0
- package/templates/xbox/src/AssetLoader.cpp +115 -12
- package/templates/xbox/src/AssetLoader.h +4 -0
- package/templates/xbox/src/EmbeddedAssets.cpp +149 -0
- package/templates/xbox/src/EmbeddedAssets.h +60 -0
- package/templates/xbox/src/EventLoop.cpp +0 -15
- package/templates/xbox/src/bindings/Audio.cpp +118 -22
- package/templates/xbox/src/bindings/Canvas.cpp +32 -2
- package/templates/xbox/src/bindings/Canvas2D.cpp +495 -39
- package/templates/xbox/src/bindings/Console.cpp +6 -1
- package/templates/xbox/src/bindings/DomShims.cpp +18 -2
- package/templates/xbox/src/bindings/EventTarget.cpp +9 -0
- package/templates/xbox/src/bindings/Image.cpp +83 -57
- package/templates/xbox/src/bindings/Polyfills.cpp +671 -236
- package/templates/xbox/src/bindings/RasterCore.h +105 -1
- package/templates/xbox/src/bindings/Video.cpp +57 -3
- package/templates/xbox/src/bindings/webgpu/WebGPU.cpp +29 -3
- package/templates/xbox/src/bindings/webgpu/WebGPUCommon.h +4 -1
- package/templates/xbox/src/bindings/webgpu/WebGPUEnums.h +32 -0
- package/templates/xbox/src/gpu/DawnContext.cpp +167 -16
- package/templates/xbox/src/main.cpp +385 -16
- package/templates/xbox/src/platform/AudioDecoder.cpp +121 -0
- package/templates/xbox/src/platform/AudioDecoder.h +18 -0
- package/templates/xbox/src/platform/AudioEngine.cpp +28 -3
- package/templates/xbox/src/platform/DecodeQueue.cpp +136 -0
- package/templates/xbox/src/platform/DecodeQueue.h +27 -0
- package/templates/xbox/src/platform/ImageDecoder.cpp +44 -0
- package/templates/xbox/src/platform/ImageDecoder.h +18 -0
- package/templates/xbox/src/platform/StbTextRasterizer.cpp +324 -0
- package/templates/xbox/src/platform/StbTextRasterizer.h +37 -0
- package/templates/xbox/src/platform/TextRasterizer.cpp +32 -0
- package/templates/xbox/src/platform/WicDecoder.cpp +19 -0
- package/templates/xbox/src/v8/CodeCache.h +223 -0
- package/templates/xbox/src/v8/V8Runtime.cpp +34 -33
- package/templates/xbox/src/v8/V8Util.h +54 -4
- package/templates/xbox/src/worker/WorkerRuntime.cpp +165 -65
- package/templates/xbox/src/worker/WorkerRuntime.h +23 -3
- package/templates/xbox/tests/check_local.sh +5 -1
- package/templates/xbox/tests/gamecore_api_probe.cpp +172 -0
- package/templates/xbox/tests/raster_test.cpp +50 -0
- package/templates/xbox/tests/windows_platform_test.cpp +75 -3
- package/templates/xbox/third_party/LICENSES.md +14 -0
- package/templates/xbox/third_party/dr_mp3.h +5412 -0
- package/templates/xbox/third_party/dr_wav.h +9131 -0
- package/templates/xbox/third_party/stb_image.h +7988 -0
- package/templates/xbox/third_party/stb_truetype.h +5079 -0
- package/templates/xbox/third_party/stb_vorbis.c +5584 -0
package/dist/xbox.js
ADDED
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
// Xbox (GDK ネイティブ) ビルド。V8 に Next2D の JS を載せ、Dawn(WebGPU/D3D12)で
|
|
2
|
+
// 描画する C++ ホストを、テンプレートのスキャフォールド → 資材配置 → pak 埋め込み →
|
|
3
|
+
// CMake/GDK ビルドの順で書き出す。
|
|
4
|
+
import pc from "picocolors";
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import os from "os";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import cp from "child_process";
|
|
9
|
+
import { minifySync } from "vite";
|
|
10
|
+
import { ctx } from "./context.js";
|
|
11
|
+
import { getTemplateDir } from "./utils.js";
|
|
12
|
+
import { XBOX_DIR_NAME, XBOX_CONFIG_NAME, XBOX_V8_VERSION, XBOX_V8_REVISION, XBOX_SCAFFOLD_EXCLUDES } from "./constants.js";
|
|
13
|
+
/**
|
|
14
|
+
* @description XboxホストのC++/CMake一式をbuilder同梱テンプレートから毎回更新する。
|
|
15
|
+
* ホストは「エンジン相当」でユーザーは編集しない前提のため、常に最新へ上書きする。
|
|
16
|
+
* ただし各ゲーム固有の `MicrosoftGame.config` は対象外(injectGameConfigが扱う)。
|
|
17
|
+
* Refresh the Xbox host (C++/CMake) from the builder's bundled template.
|
|
18
|
+
*
|
|
19
|
+
* @return {Promise}
|
|
20
|
+
* @method
|
|
21
|
+
* @private
|
|
22
|
+
*/
|
|
23
|
+
const refreshXboxHost = () => {
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
const projectDir = `${process.cwd()}/${XBOX_DIR_NAME}`;
|
|
26
|
+
const templateDir = getTemplateDir("xbox");
|
|
27
|
+
if (!fs.existsSync(templateDir)) {
|
|
28
|
+
return reject(`Xbox template not found: ${templateDir}`);
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
fs.cpSync(templateDir, projectDir, {
|
|
32
|
+
"recursive": true,
|
|
33
|
+
// ゲーム固有設定と builder 側の開発用ファイルはスキャフォールドしない
|
|
34
|
+
"filter": (src) => !XBOX_SCAFFOLD_EXCLUDES.has(path.basename(src))
|
|
35
|
+
});
|
|
36
|
+
console.log(pc.green(`Successfully refreshed \`${XBOX_DIR_NAME}\` host.`));
|
|
37
|
+
resolve();
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
reject(`Failed to refresh ${XBOX_DIR_NAME} host. ${error}`);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* @description ゲームルートの `MicrosoftGame.config` をXboxホストへ注入する。
|
|
46
|
+
* 未配置ならbuilder同梱の既定をフォールバックとして使い、作成を促す。
|
|
47
|
+
* Inject the game-root `MicrosoftGame.config` into the Xbox host.
|
|
48
|
+
*
|
|
49
|
+
* @return {Promise}
|
|
50
|
+
* @method
|
|
51
|
+
* @private
|
|
52
|
+
*/
|
|
53
|
+
const injectGameConfig = () => {
|
|
54
|
+
return new Promise((resolve, reject) => {
|
|
55
|
+
const rootConfig = `${process.cwd()}/${XBOX_CONFIG_NAME}`;
|
|
56
|
+
const hostConfig = `${process.cwd()}/${XBOX_DIR_NAME}/${XBOX_CONFIG_NAME}`;
|
|
57
|
+
try {
|
|
58
|
+
if (fs.existsSync(rootConfig)) {
|
|
59
|
+
fs.cpSync(rootConfig, hostConfig);
|
|
60
|
+
console.log(pc.green(`Applied project \`${XBOX_CONFIG_NAME}\`.`));
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
// フォールバック: builder同梱の既定を配置し、ルートへの作成を促す
|
|
64
|
+
fs.cpSync(`${getTemplateDir("xbox")}/${XBOX_CONFIG_NAME}`, hostConfig);
|
|
65
|
+
console.log(pc.yellow(`\`${XBOX_CONFIG_NAME}\` not found at project root. Using the default template.`));
|
|
66
|
+
console.log(pc.yellow(`Create \`${XBOX_CONFIG_NAME}\` at your project root (like capacitor.config.json) to set TitleId/StoreId/logos.`));
|
|
67
|
+
}
|
|
68
|
+
resolve();
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
reject(`Failed to apply ${XBOX_CONFIG_NAME}. ${error}`);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* @description ビルド済みWeb資材(JS/HTML/アセット)をXboxホストのassetsへ配置
|
|
77
|
+
* Deploy built web resources (JS/HTML/assets) into the Xbox host assets
|
|
78
|
+
*
|
|
79
|
+
* @return {Promise}
|
|
80
|
+
* @method
|
|
81
|
+
* @private
|
|
82
|
+
*/
|
|
83
|
+
const copyXboxResources = () => {
|
|
84
|
+
return new Promise((resolve, reject) => {
|
|
85
|
+
const assetsDir = `${process.cwd()}/${XBOX_DIR_NAME}/assets/app`;
|
|
86
|
+
try {
|
|
87
|
+
// reset
|
|
88
|
+
fs.rmSync(assetsDir, { "recursive": true, "force": true });
|
|
89
|
+
fs.mkdirSync(assetsDir, { "recursive": true });
|
|
90
|
+
// copy built web resources (JS/HTML/assets)
|
|
91
|
+
fs.cpSync(`${ctx.buildDir}/`, assetsDir, { "recursive": true });
|
|
92
|
+
console.log(pc.green("Successfully copy built resources to Xbox host."));
|
|
93
|
+
resolve();
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
reject(`Failed to copy built resources to Xbox host. ${error}`);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* @description ディレクトリを再帰的に走査し、各ファイルの
|
|
102
|
+
* [posix 相対キー, 絶対パス] を集める。
|
|
103
|
+
* Walk a directory recursively, collecting [posixRelKey, absPath] pairs.
|
|
104
|
+
*
|
|
105
|
+
* @param {string} rootDir 走査ルート
|
|
106
|
+
* @param {string} [prefix] キーへ付与する接頭辞 (例 "" / "assets/")
|
|
107
|
+
* @return {Array<[string, string]>}
|
|
108
|
+
* @method
|
|
109
|
+
* @public
|
|
110
|
+
*/
|
|
111
|
+
export const walkFiles = (rootDir, prefix = "") => {
|
|
112
|
+
const out = [];
|
|
113
|
+
if (!fs.existsSync(rootDir)) {
|
|
114
|
+
return out;
|
|
115
|
+
}
|
|
116
|
+
for (const entry of fs.readdirSync(rootDir, { "withFileTypes": true })) {
|
|
117
|
+
const abs = path.join(rootDir, entry.name);
|
|
118
|
+
const key = prefix ? `${prefix}${entry.name}` : entry.name;
|
|
119
|
+
if (entry.isDirectory()) {
|
|
120
|
+
out.push(...walkFiles(abs, `${key}/`));
|
|
121
|
+
}
|
|
122
|
+
else if (entry.isFile()) {
|
|
123
|
+
out.push([key, abs]);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return out;
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* @description (key, データ) の並びを exe 埋め込み用 pak バイナリへ直列化する純関数。
|
|
130
|
+
* host 側 EmbeddedAssets.cpp の ParseEmbeddedPak と対になる。
|
|
131
|
+
* フォーマット (リトルエンディアン uint32):
|
|
132
|
+
* magic "N2DA" / version(=1) / count / [keyLen,key,dataLen,data]...
|
|
133
|
+
* Serialize (key, data) entries into the embedded pak binary.
|
|
134
|
+
*
|
|
135
|
+
* @param {Array<[string, Buffer]>} entries
|
|
136
|
+
* @return {Buffer}
|
|
137
|
+
* @method
|
|
138
|
+
* @public
|
|
139
|
+
*/
|
|
140
|
+
export const buildPak = (entries) => {
|
|
141
|
+
const chunks = [];
|
|
142
|
+
const header = Buffer.alloc(12);
|
|
143
|
+
header.write("N2DA", 0, "ascii");
|
|
144
|
+
header.writeUInt32LE(1, 4); // version
|
|
145
|
+
header.writeUInt32LE(entries.length, 8); // count
|
|
146
|
+
chunks.push(header);
|
|
147
|
+
for (const [key, data] of entries) {
|
|
148
|
+
const keyBuf = Buffer.from(key, "utf8");
|
|
149
|
+
const meta = Buffer.alloc(4);
|
|
150
|
+
meta.writeUInt32LE(keyBuf.length, 0);
|
|
151
|
+
chunks.push(meta, keyBuf);
|
|
152
|
+
const meta2 = Buffer.alloc(4);
|
|
153
|
+
meta2.writeUInt32LE(data.length, 0);
|
|
154
|
+
chunks.push(meta2, data);
|
|
155
|
+
}
|
|
156
|
+
return Buffer.concat(chunks);
|
|
157
|
+
};
|
|
158
|
+
/**
|
|
159
|
+
* @description assets.pak を RCDATA "N2DASSETS" として取り込む .rc の内容を生成する純関数。
|
|
160
|
+
* 相対パスだと rc.exe の CWD (build ディレクトリ) 基準で探して見つからない
|
|
161
|
+
* (RC2135) ため絶対パスを埋める。RC はフォワードスラッシュを受理する。
|
|
162
|
+
* 文字列は必ずダブルクォート (RC 仕様。シングルクォートは不可)。
|
|
163
|
+
* Render the .rc content that embeds assets.pak as RCDATA.
|
|
164
|
+
*
|
|
165
|
+
* @param {string} pakAbsPath assets.pak の絶対パス
|
|
166
|
+
* @return {string}
|
|
167
|
+
* @method
|
|
168
|
+
* @public
|
|
169
|
+
*/
|
|
170
|
+
export const renderAssetsRc = (pakAbsPath) => {
|
|
171
|
+
const forward = pakAbsPath.replace(/\\/g, "/");
|
|
172
|
+
return `N2DASSETS RCDATA "${forward}"\n`;
|
|
173
|
+
};
|
|
174
|
+
/**
|
|
175
|
+
* @description ホストスクリプト(js/bootstrap.js 等)を minify + 難読化する純関数。
|
|
176
|
+
* Oxc(vite 同梱)でコメント除去・空白圧縮・ローカル識別子マングルを行う。
|
|
177
|
+
* `globalThis.*` 等のグローバル名はゲームが参照するため保持される。
|
|
178
|
+
* 失敗時は元コードをそのまま返す(埋め込み自体は継続)。
|
|
179
|
+
* Minify/obfuscate a host script; returns the original on failure.
|
|
180
|
+
*
|
|
181
|
+
* @param {string} name ファイル名 (拡張子で構文判定)
|
|
182
|
+
* @param {string} code 元の JavaScript
|
|
183
|
+
* @return {string}
|
|
184
|
+
* @method
|
|
185
|
+
* @public
|
|
186
|
+
*/
|
|
187
|
+
export const minifyJs = (name, code) => {
|
|
188
|
+
try {
|
|
189
|
+
const result = minifySync(name, code);
|
|
190
|
+
if (result.errors && result.errors.length > 0) {
|
|
191
|
+
const msg = result.errors[0]?.message ?? String(result.errors[0]);
|
|
192
|
+
console.log(pc.yellow(`Xbox: minify skipped for ${name} (${msg}); embedding as-is.`));
|
|
193
|
+
return code;
|
|
194
|
+
}
|
|
195
|
+
return result.code;
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
console.log(pc.yellow(`Xbox: minify failed for ${name}; embedding as-is. ${error}`));
|
|
199
|
+
return code;
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
/**
|
|
203
|
+
* @description Xbox ホストの assets/app とホストスクリプト(js/bootstrap.js 等)を
|
|
204
|
+
* 単一の pak バイナリへまとめ、`assets.pak` と RCDATA 参照用の
|
|
205
|
+
* `assets.rc` を xbox/ 直下へ生成する。CMake が assets.rc を検出して
|
|
206
|
+
* これらを exe 内リソースへ**必ず**埋め込み、平文 JS/HTML を配布物に残さない。
|
|
207
|
+
* 埋め込みは必須(非埋め込みの選択肢は無い)。資材が無ければハードエラー。
|
|
208
|
+
*
|
|
209
|
+
* pak フォーマット (リトルエンディアン uint32):
|
|
210
|
+
* magic "N2DA" / version(=1) / count / [keyLen,key,dataLen,data]...
|
|
211
|
+
* キーは assets/app 基準の posix 相対パス、または "js/bootstrap.js"。
|
|
212
|
+
* host 側 EmbeddedAssets.cpp の ParseEmbeddedPak と対になる。
|
|
213
|
+
*
|
|
214
|
+
* @return {Promise}
|
|
215
|
+
* @method
|
|
216
|
+
* @private
|
|
217
|
+
*/
|
|
218
|
+
const embedXboxAssets = () => {
|
|
219
|
+
return new Promise((resolve, reject) => {
|
|
220
|
+
const xboxDir = `${process.cwd()}/${XBOX_DIR_NAME}`;
|
|
221
|
+
const pakPath = `${xboxDir}/assets.pak`;
|
|
222
|
+
const rcPath = `${xboxDir}/assets.rc`;
|
|
223
|
+
try {
|
|
224
|
+
// 収集: assets/app 一式 (キーは app 基準) + host スクリプト (js/ 基準)。
|
|
225
|
+
const entries = [];
|
|
226
|
+
entries.push(...walkFiles(`${xboxDir}/assets/app`, ""));
|
|
227
|
+
const bootstrap = `${xboxDir}/js/bootstrap.js`;
|
|
228
|
+
if (fs.existsSync(bootstrap)) {
|
|
229
|
+
entries.push(["js/bootstrap.js", bootstrap]);
|
|
230
|
+
}
|
|
231
|
+
const selftest = `${xboxDir}/js/selftest.js`;
|
|
232
|
+
if (fs.existsSync(selftest)) {
|
|
233
|
+
entries.push(["js/selftest.js", selftest]);
|
|
234
|
+
}
|
|
235
|
+
if (entries.length === 0) {
|
|
236
|
+
return reject("No Xbox assets found to embed (assets/app is empty).");
|
|
237
|
+
}
|
|
238
|
+
// (key, データ) を読み込み、pak バイナリへ直列化する。
|
|
239
|
+
// js/ のホストスクリプト(bootstrap.js/selftest.js)は minify + 難読化する。
|
|
240
|
+
// assets/app の JS は vite が本番ビルドで minify 済みのためそのまま。
|
|
241
|
+
let minified = 0;
|
|
242
|
+
const pakEntries = entries.map(([key, abs]) => {
|
|
243
|
+
if (key.startsWith("js/") && key.endsWith(".js")) {
|
|
244
|
+
const src = fs.readFileSync(abs, { "encoding": "utf8" });
|
|
245
|
+
const out = minifyJs(key, src);
|
|
246
|
+
if (out.length < src.length) {
|
|
247
|
+
++minified;
|
|
248
|
+
}
|
|
249
|
+
return [key, Buffer.from(out, "utf8")];
|
|
250
|
+
}
|
|
251
|
+
return [key, fs.readFileSync(abs)];
|
|
252
|
+
});
|
|
253
|
+
const pak = buildPak(pakEntries);
|
|
254
|
+
if (minified > 0) {
|
|
255
|
+
console.log(pc.green(`Minified ${minified} host script(s) before embedding.`));
|
|
256
|
+
}
|
|
257
|
+
fs.writeFileSync(pakPath, pak);
|
|
258
|
+
// rc.exe が assets.pak を RCDATA "N2DASSETS" として取り込む .rc を生成する。
|
|
259
|
+
fs.writeFileSync(rcPath, renderAssetsRc(path.resolve(pakPath)), "utf8");
|
|
260
|
+
console.log(pc.green(`Embedded ${entries.length} Xbox asset file(s) into assets.pak `
|
|
261
|
+
+ `(${(pak.length / 1024 / 1024).toFixed(2)} MB).`));
|
|
262
|
+
// 埋め込み済みの平文 `assets/`・`js/` は書き出し一覧から除外する。
|
|
263
|
+
// これらは assets.pak (=exe 内 RCDATA) に格納済みで、CMake も埋め込みモードでは
|
|
264
|
+
// exe 隣へステージしないため、xbox/ 直下に残しても不要かつ平文流出になる。
|
|
265
|
+
fs.rmSync(`${xboxDir}/assets`, { "recursive": true, "force": true });
|
|
266
|
+
fs.rmSync(`${xboxDir}/js`, { "recursive": true, "force": true });
|
|
267
|
+
console.log(pc.green("Excluded plaintext `assets/` and `js/` from the export (embedded in exe)."));
|
|
268
|
+
resolve();
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
reject(`Failed to embed Xbox assets. ${error}`);
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
};
|
|
275
|
+
/**
|
|
276
|
+
* @description Xbox ビルドに使う V8 のパスを解決する。優先順:
|
|
277
|
+
* 1. `--v8-root` 引数
|
|
278
|
+
* 2. 環境変数 `V8_ROOT`
|
|
279
|
+
* 3. キャッシュ済みの prebuilt (%LOCALAPPDATA%/next2d/v8/<version>)
|
|
280
|
+
* 4. GitHub Releases (build-v8.yml が発行) から自動ダウンロード
|
|
281
|
+
* 3・4 により、通常は何も指定せずに `--platform xbox` だけでビルドできる。
|
|
282
|
+
* Resolve the V8 path for the Xbox build.
|
|
283
|
+
*
|
|
284
|
+
* @return {Promise<string>}
|
|
285
|
+
* @method
|
|
286
|
+
* @private
|
|
287
|
+
*/
|
|
288
|
+
const resolveXboxV8Root = async () => {
|
|
289
|
+
// 1. --v8-root 引数
|
|
290
|
+
if (ctx.v8Root) {
|
|
291
|
+
return path.resolve(process.cwd(), ctx.v8Root);
|
|
292
|
+
}
|
|
293
|
+
// 2. 環境変数 V8_ROOT
|
|
294
|
+
if (process.env.V8_ROOT) {
|
|
295
|
+
return process.env.V8_ROOT;
|
|
296
|
+
}
|
|
297
|
+
// 3. キャッシュ済み prebuilt
|
|
298
|
+
const cacheBase = process.env.LOCALAPPDATA
|
|
299
|
+
? `${process.env.LOCALAPPDATA}/next2d`
|
|
300
|
+
: `${os.homedir()}/.cache/next2d`;
|
|
301
|
+
const cacheDir = `${cacheBase}/v8/${XBOX_V8_VERSION}-${XBOX_V8_REVISION}`;
|
|
302
|
+
if (fs.existsSync(`${cacheDir}/include/v8.h`)) {
|
|
303
|
+
return cacheDir;
|
|
304
|
+
}
|
|
305
|
+
// 4. GitHub Releases から自動ダウンロード (マシンごとに初回のみ)
|
|
306
|
+
const assetName = `v8-monolith-${XBOX_V8_VERSION}-windows-x64.zip`;
|
|
307
|
+
const url = `https://github.com/Next2D/builder/releases/download/v8-${XBOX_V8_VERSION}-windows-x64-${XBOX_V8_REVISION}/${assetName}`;
|
|
308
|
+
console.log(pc.green(`Downloading prebuilt V8 ${XBOX_V8_VERSION} (first time only) ...`));
|
|
309
|
+
console.log(url);
|
|
310
|
+
const response = await fetch(url);
|
|
311
|
+
if (!response.ok) {
|
|
312
|
+
throw new Error(`download failed: HTTP ${response.status}`);
|
|
313
|
+
}
|
|
314
|
+
fs.mkdirSync(cacheDir, { "recursive": true });
|
|
315
|
+
const zipPath = `${cacheDir}/${assetName}.tmp`;
|
|
316
|
+
fs.writeFileSync(zipPath, Buffer.from(await response.arrayBuffer()));
|
|
317
|
+
// Windows 10+ 標準の tar (bsdtar) は zip も展開できる
|
|
318
|
+
const extract = cp.spawnSync("tar", ["-xf", zipPath, "-C", cacheDir], { "stdio": "inherit" });
|
|
319
|
+
fs.rmSync(zipPath, { "force": true });
|
|
320
|
+
if (extract.status !== 0 || !fs.existsSync(`${cacheDir}/include/v8.h`)) {
|
|
321
|
+
fs.rmSync(cacheDir, { "recursive": true, "force": true });
|
|
322
|
+
throw new Error("failed to extract the prebuilt V8 archive");
|
|
323
|
+
}
|
|
324
|
+
console.log(pc.green(`Prebuilt V8 cached at: ${cacheDir}`));
|
|
325
|
+
return cacheDir;
|
|
326
|
+
};
|
|
327
|
+
/**
|
|
328
|
+
* @description Xbox(GDKネイティブ)用アプリの書き出し関数。
|
|
329
|
+
* V8にNext2DのJSを載せ、Dawn(WebGPU/D3D12)で描画するC++ホストをビルドする。
|
|
330
|
+
* Export function for Xbox (GDK native) apps.
|
|
331
|
+
*
|
|
332
|
+
* @return {Promise}
|
|
333
|
+
* @method
|
|
334
|
+
* @public
|
|
335
|
+
*/
|
|
336
|
+
export const buildXbox = async () => {
|
|
337
|
+
// C++/CMake ホストを最新へ更新 (ゲーム固有設定は除外)
|
|
338
|
+
await refreshXboxHost();
|
|
339
|
+
// ゲームルートの MicrosoftGame.config を注入
|
|
340
|
+
await injectGameConfig();
|
|
341
|
+
// ビルド済みWeb資材を配置
|
|
342
|
+
await copyXboxResources();
|
|
343
|
+
// assets/app + host スクリプトを exe 埋め込み用 pak (+ rc) へまとめる
|
|
344
|
+
await embedXboxAssets();
|
|
345
|
+
/**
|
|
346
|
+
* GDK ビルドは Windows + Visual Studio + Microsoft GDK が必須。
|
|
347
|
+
* それ以外の環境ではスキャフォールドと資材配置のみを行い、手順を案内する。
|
|
348
|
+
* The GDK build requires Windows + Visual Studio + Microsoft GDK.
|
|
349
|
+
*/
|
|
350
|
+
if (process.platform !== "win32") {
|
|
351
|
+
console.log();
|
|
352
|
+
console.log(pc.yellow("Xbox host project has been generated and assets were copied."));
|
|
353
|
+
console.log(pc.yellow("The GDK build must run on Windows with Visual Studio and the Microsoft GDK installed."));
|
|
354
|
+
console.log(pc.yellow(`See ${XBOX_DIR_NAME}/README.md for the build steps.`));
|
|
355
|
+
console.log();
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* @type {string}
|
|
360
|
+
* GDK の対象コンソール世代。既定は Xbox Series X|S (Scarlett)。
|
|
361
|
+
*/
|
|
362
|
+
const gdkArch = process.env.NEXT2D_XBOX_ARCH || "Gaming.Xbox.Scarlett.x64";
|
|
363
|
+
const cmakeBuildDir = `${process.cwd()}/${ctx.outDir}/${ctx.platformDir}/build`;
|
|
364
|
+
/**
|
|
365
|
+
* prebuilt V8 のパスを解決する (--v8-root > V8_ROOT > キャッシュ > 自動ダウンロード)。
|
|
366
|
+
*/
|
|
367
|
+
let resolvedV8Root = "";
|
|
368
|
+
try {
|
|
369
|
+
resolvedV8Root = await resolveXboxV8Root();
|
|
370
|
+
}
|
|
371
|
+
catch (error) {
|
|
372
|
+
console.log(pc.red(`Failed to prepare the prebuilt V8: ${error}`));
|
|
373
|
+
console.log(pc.red("Fallbacks:"));
|
|
374
|
+
console.log(pc.red(" 1) Retry later (the download may have failed temporarily)."));
|
|
375
|
+
console.log(pc.red(" 2) Build V8 yourself and pass `--v8-root <path>`:"));
|
|
376
|
+
console.log(pc.red(" npx @next2d/builder --platform xbox --env prd --v8-root C:\\path\\to\\v8"));
|
|
377
|
+
console.log(pc.red(` See ${XBOX_DIR_NAME}/README.md ("V8 の用意") for the build steps.`));
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
if (!fs.existsSync(`${resolvedV8Root}/include/v8.h`)) {
|
|
381
|
+
console.log(pc.red(`\`include/v8.h\` not found under: ${resolvedV8Root}`));
|
|
382
|
+
console.log(pc.red(`Check the \`--v8-root\` path. See ${XBOX_DIR_NAME}/README.md for how to prepare the prebuilt V8.`));
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
const configure = () => {
|
|
386
|
+
return new Promise((resolve, reject) => {
|
|
387
|
+
const stream = cp.spawn("cmake", [
|
|
388
|
+
"-S", `${process.cwd()}/${XBOX_DIR_NAME}`,
|
|
389
|
+
"-B", cmakeBuildDir,
|
|
390
|
+
"-G", "Visual Studio 17 2022",
|
|
391
|
+
"-A", gdkArch,
|
|
392
|
+
"-D", `V8_ROOT=${resolvedV8Root}`
|
|
393
|
+
], { "stdio": "inherit" });
|
|
394
|
+
stream.on("close", (code) => {
|
|
395
|
+
if (code !== 0) {
|
|
396
|
+
return reject("Failed to configure the Xbox (CMake/GDK) project.");
|
|
397
|
+
}
|
|
398
|
+
resolve();
|
|
399
|
+
});
|
|
400
|
+
});
|
|
401
|
+
};
|
|
402
|
+
await configure();
|
|
403
|
+
if (ctx.open || ctx.preview) {
|
|
404
|
+
// Visual Studio ソリューションを開く (実機/エミュレータでの実行はVS側で行う)
|
|
405
|
+
cp.spawn("cmake", [
|
|
406
|
+
"--open", cmakeBuildDir
|
|
407
|
+
], { "stdio": "inherit" });
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
// フルビルド (Release パッケージまで)。失敗時は reject して非ゼロ終了させる
|
|
411
|
+
await new Promise((resolve, reject) => {
|
|
412
|
+
const stream = cp.spawn("cmake", [
|
|
413
|
+
"--build", cmakeBuildDir,
|
|
414
|
+
"--config", "Release"
|
|
415
|
+
], { "stdio": "inherit" });
|
|
416
|
+
stream.on("close", (code) => {
|
|
417
|
+
if (code !== 0) {
|
|
418
|
+
return reject("Export of the Xbox (GDK) package failed.");
|
|
419
|
+
}
|
|
420
|
+
console.log();
|
|
421
|
+
console.log(pc.green(`Finished building the Xbox (GDK) package for ${gdkArch}.`));
|
|
422
|
+
console.log();
|
|
423
|
+
resolve();
|
|
424
|
+
});
|
|
425
|
+
});
|
|
426
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@next2d/builder",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"description": "Multi-platform builder for Next2d Framework, supporting export to various platforms such as macOS, Windows, iOS, Android and Web(HTML)",
|
|
5
5
|
"author": "Toshiyuki Ienaga <ienaga@next2d.app>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -21,7 +21,9 @@
|
|
|
21
21
|
"Multi-platform builder"
|
|
22
22
|
],
|
|
23
23
|
"scripts": {
|
|
24
|
-
"lint": "eslint src
|
|
24
|
+
"lint": "eslint src",
|
|
25
|
+
"build": "tsc",
|
|
26
|
+
"test": "tsc && node --test \"tests/**/*.test.ts\"",
|
|
25
27
|
"prepare": "tsc",
|
|
26
28
|
"release": "tsc"
|
|
27
29
|
},
|
|
@@ -38,18 +40,18 @@
|
|
|
38
40
|
},
|
|
39
41
|
"dependencies": {
|
|
40
42
|
"@electron-forge/core": "^7.11.2",
|
|
41
|
-
"@types/node": "^26.
|
|
43
|
+
"@types/node": "^26.4.0",
|
|
42
44
|
"picocolors": "^1.1.1",
|
|
43
|
-
"vite": "^8.
|
|
45
|
+
"vite": "^8.2.2"
|
|
44
46
|
},
|
|
45
47
|
"devDependencies": {
|
|
46
|
-
"@eslint/eslintrc": "^3.3.
|
|
48
|
+
"@eslint/eslintrc": "^3.3.7",
|
|
47
49
|
"@eslint/js": "^10.0.1",
|
|
48
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
49
|
-
"@typescript-eslint/parser": "^8.
|
|
50
|
-
"eslint": "^10.
|
|
50
|
+
"@typescript-eslint/eslint-plugin": "^8.69.0",
|
|
51
|
+
"@typescript-eslint/parser": "^8.69.0",
|
|
52
|
+
"eslint": "^10.9.1",
|
|
51
53
|
"eslint-plugin-unused-imports": "^4.4.1",
|
|
52
|
-
"globals": "^17.
|
|
54
|
+
"globals": "^17.12.0",
|
|
53
55
|
"typescript": "^6.0.3"
|
|
54
56
|
}
|
|
55
57
|
}
|
|
@@ -89,10 +89,24 @@ file(GLOB_RECURSE NEXT2D_HOST_SOURCES
|
|
|
89
89
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.h"
|
|
90
90
|
)
|
|
91
91
|
|
|
92
|
+
# 埋め込みアセット: builder の buildXbox が assets.pak と assets.rc を必ず生成し、
|
|
93
|
+
# RCDATA "N2DASSETS" として exe にリンクする (ゲーム JS/HTML は平文で隣に置かない)。
|
|
94
|
+
# 埋め込みは必須。assets.rc が無いのは builder を経由せず cmake を直接叩いた
|
|
95
|
+
# ホスト単体ビルド (ゲーム資材なし) のみで、その場合はゲームは起動しない。
|
|
96
|
+
set(NEXT2D_ASSETS_RC "${CMAKE_CURRENT_SOURCE_DIR}/assets.rc")
|
|
97
|
+
if(EXISTS "${NEXT2D_ASSETS_RC}")
|
|
98
|
+
enable_language(RC)
|
|
99
|
+
list(APPEND NEXT2D_HOST_SOURCES "${NEXT2D_ASSETS_RC}")
|
|
100
|
+
message(STATUS "Next2D: embedding assets from ${NEXT2D_ASSETS_RC}")
|
|
101
|
+
else()
|
|
102
|
+
message(WARNING "Next2D: assets.rc not found - host-only build (no game assets). Run @next2d/builder to embed.")
|
|
103
|
+
endif()
|
|
104
|
+
|
|
92
105
|
add_executable(Next2DXboxHost WIN32 ${NEXT2D_HOST_SOURCES})
|
|
93
106
|
|
|
94
107
|
target_include_directories(Next2DXboxHost PRIVATE
|
|
95
108
|
"${CMAKE_CURRENT_SOURCE_DIR}/src"
|
|
109
|
+
"${CMAKE_CURRENT_SOURCE_DIR}" # third_party/ (stb_image, dr_mp3 等)
|
|
96
110
|
)
|
|
97
111
|
|
|
98
112
|
# 展開レイアウト (GDK_ROOT) 使用時: include/lib を明示指定し、実行時 DLL を並べる
|
|
@@ -124,6 +138,20 @@ if(MSVC)
|
|
|
124
138
|
# Release でも PDB を生成する (クラッシュダンプ解析でスタックを名前解決するため)
|
|
125
139
|
target_compile_options(Next2DXboxHost PRIVATE /Zi)
|
|
126
140
|
target_link_options(Next2DXboxHost PRIVATE /DEBUG /OPT:REF /OPT:ICF)
|
|
141
|
+
|
|
142
|
+
# Release: リンク時コード生成 (LTCG)。翻訳単位を跨いだインライン化が効き、
|
|
143
|
+
# 毎フレーム通る V8 バインディング層 (小さな関数の呼び出し連鎖) に有効。
|
|
144
|
+
# (VS ジェネレータでは COMPILE_OPTIONS は C++ (ClCompile) にのみ渡り、
|
|
145
|
+
# RC (assets.rc) には影響しない。/Zi と同じ流儀)
|
|
146
|
+
target_compile_options(Next2DXboxHost PRIVATE $<$<CONFIG:Release>:/GL>)
|
|
147
|
+
target_link_options(Next2DXboxHost PRIVATE $<$<CONFIG:Release>:/LTCG>)
|
|
148
|
+
|
|
149
|
+
# /arch:AVX2: Xbox Series X|S (Zen 2) と Haswell (2013) 以降の PC で動作。
|
|
150
|
+
# ソフトラスタ (RasterCore) や pak 解析などホスト C++ の自動ベクトル化が進む。
|
|
151
|
+
# Xbox One (Jaguar) は AVX2 非対応のため除外する。
|
|
152
|
+
if(NOT CMAKE_GENERATOR_PLATFORM MATCHES "XboxOne")
|
|
153
|
+
target_compile_options(Next2DXboxHost PRIVATE /arch:AVX2)
|
|
154
|
+
endif()
|
|
127
155
|
endif()
|
|
128
156
|
|
|
129
157
|
# webgpu_dawn は SHARED (DLL)。実行に必要なため exe の隣へステージする
|
|
@@ -135,14 +163,25 @@ if(TARGET webgpu_dawn)
|
|
|
135
163
|
COMMENT "Staging webgpu_dawn.dll next to the executable")
|
|
136
164
|
endif()
|
|
137
165
|
|
|
138
|
-
# WebGPU / D3D12 / GameInput /
|
|
166
|
+
# WebGPU / D3D12 / GameInput / XAudio2 / GDK
|
|
139
167
|
target_link_libraries(Next2DXboxHost PRIVATE
|
|
140
168
|
d3d12
|
|
141
169
|
dxgi
|
|
142
170
|
dxguid
|
|
143
|
-
windowscodecs # WIC: 画像デコード
|
|
144
171
|
)
|
|
145
172
|
|
|
173
|
+
if(NOT NEXT2D_IS_CONSOLE)
|
|
174
|
+
# デスクトップ専用 (Game Core OS に存在しない):
|
|
175
|
+
# windowscodecs = WIC (stb_image で扱えない形式の画像デコードフォールバック)
|
|
176
|
+
# dbghelp = クラッシュハンドラのスタックトレース (StackWalk64/SymFromAddr)
|
|
177
|
+
# MF (mfplat 等)/d2d1/dwrite/shlwapi/winmm はソース側の #pragma comment(lib) が
|
|
178
|
+
# 同じ NEXT2D_XBOX_CONSOLE ガード内でリンク指示する。
|
|
179
|
+
target_link_libraries(Next2DXboxHost PRIVATE
|
|
180
|
+
windowscodecs
|
|
181
|
+
dbghelp
|
|
182
|
+
)
|
|
183
|
+
endif()
|
|
184
|
+
|
|
146
185
|
if(NEXT2D_IS_CONSOLE)
|
|
147
186
|
# コンソール用ライブラリ (GDK が提供)
|
|
148
187
|
target_link_libraries(Next2DXboxHost PRIVATE
|
|
@@ -176,18 +215,15 @@ target_compile_definitions(Next2DXboxHost PRIVATE
|
|
|
176
215
|
|
|
177
216
|
# -----------------------------------------------------------------------------
|
|
178
217
|
# ランタイム資材のステージング
|
|
179
|
-
#
|
|
180
|
-
#
|
|
218
|
+
# ゲーム JS/HTML/アセット (assets/app) とホストスクリプト (js/bootstrap.js) は
|
|
219
|
+
# builder が assets.pak にまとめて exe 内 RCDATA へ**必ず**埋め込む
|
|
220
|
+
# (非埋め込みの選択肢は無い。平文 JS/HTML を配布物に残さないのが目的)。
|
|
221
|
+
# したがって exe 隣へは assets/ も js/ もコピーしない。
|
|
222
|
+
# MicrosoftGame.config (GDK タイトル設定) だけを exe の隣へステージングする。
|
|
181
223
|
# -----------------------------------------------------------------------------
|
|
182
224
|
add_custom_command(TARGET Next2DXboxHost POST_BUILD
|
|
183
|
-
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
184
|
-
"${CMAKE_CURRENT_SOURCE_DIR}/assets"
|
|
185
|
-
"$<TARGET_FILE_DIR:Next2DXboxHost>/assets"
|
|
186
|
-
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
187
|
-
"${CMAKE_CURRENT_SOURCE_DIR}/js"
|
|
188
|
-
"$<TARGET_FILE_DIR:Next2DXboxHost>/js"
|
|
189
225
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
190
226
|
"${CMAKE_CURRENT_SOURCE_DIR}/MicrosoftGame.config"
|
|
191
227
|
"$<TARGET_FILE_DIR:Next2DXboxHost>/MicrosoftGame.config"
|
|
192
|
-
COMMENT "Staging
|
|
228
|
+
COMMENT "Staging MicrosoftGame.config (assets/JS embedded in exe)"
|
|
193
229
|
)
|
package/templates/xbox/README.md
CHANGED
|
@@ -378,3 +378,21 @@ xbox/
|
|
|
378
378
|
├─ Gamepad.cpp DomShims.cpp
|
|
379
379
|
└─ webgpu/{WebGPU.cpp,WebGPUCommon.h,WebGPUEnums.h}
|
|
380
380
|
```
|
|
381
|
+
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
## コンソール (Game Core OS) とテキスト描画・フォント
|
|
385
|
+
|
|
386
|
+
コンソールには DirectWrite / システムフォントが存在しないため、`fillText`/`measureText`
|
|
387
|
+
は同梱の stb_truetype 実装 (`platform/StbTextRasterizer`) が担う。フォントは実行時登録:
|
|
388
|
+
|
|
389
|
+
- **ゲーム資材に TTF/OTF を含める**(推奨): Web ビルドの資材 (`assets/app`) に
|
|
390
|
+
`*.ttf` / `*.otf` があれば起動時に自動登録される (vite の `public/` に置く等)。
|
|
391
|
+
日本語テキストを使う場合は Noto Sans JP (OFL) などの同梱を推奨。
|
|
392
|
+
- 開発ビルド: exe 隣接の `fonts/` ディレクトリからも読み込む。
|
|
393
|
+
- フォント未登録の場合、テキストは近似メトリクスのみ (グリフ描画なし) になる。
|
|
394
|
+
|
|
395
|
+
デスクトップ (PC/GDK) は従来どおり DirectWrite が主経路のため、フォント同梱は不要。
|
|
396
|
+
同様に、画像は stb_image、音声は dr_mp3/dr_wav/stb_vorbis が全プラットフォーム共通の
|
|
397
|
+
第一経路で、WIC / Media Foundation はデスクトップ限定のフォールバック
|
|
398
|
+
(AAC/TIFF 等の非標準形式向け)。コンソールでの動画 (`<video>`) は未対応。
|