371 lines
9.7 KiB
Markdown
371 lines
9.7 KiB
Markdown
# Frostbite2D 编译说明
|
||
|
||
本文档记录当前 Windows PC 和 Nintendo Switch 版本的编译方法。命令默认在项目根目录执行:
|
||
|
||
```powershell
|
||
cd X:\NS_unknown_game\Frostbite2D-Engine
|
||
```
|
||
|
||
## 1. Windows PC 编译
|
||
|
||
### 1.1 前置环境
|
||
|
||
当前机器已验证可用:
|
||
|
||
- Visual Studio 2026 MSVC x64 工具链
|
||
- XMake:`C:\Program Files\xmake\xmake.exe`
|
||
- CMake:`C:\Program Files\CMake\bin\cmake.exe`
|
||
- Python 3.13,供 XMake 构建部分依赖包使用
|
||
|
||
XMake 会自动拉取这些 PC 依赖:
|
||
|
||
- SDL2
|
||
- SDL2_image
|
||
- SDL2_mixer
|
||
- SDL2_ttf
|
||
- GLM
|
||
- zlib
|
||
|
||
### 1.2 编译引擎静态库
|
||
|
||
```powershell
|
||
$env:PATH='C:\Program Files\CMake\bin;C:\Program Files\xmake;' + $env:PATH
|
||
|
||
& 'C:\Program Files\xmake\xmake.exe' f -c -p windows -a x64 -m release -y
|
||
& 'C:\Program Files\xmake\xmake.exe' build Frostbite2D
|
||
```
|
||
|
||
产物:
|
||
|
||
```text
|
||
build\windows\x64\release\Frostbite2D.lib
|
||
```
|
||
|
||
### 1.3 编译 Windows 测试 EXE
|
||
|
||
项目内有一个最小 Windows 测试程序:
|
||
|
||
```text
|
||
examples\windows_smoke\main.cpp
|
||
```
|
||
|
||
编译命令:
|
||
|
||
```powershell
|
||
$env:PATH='C:\Program Files\CMake\bin;C:\Program Files\xmake;' + $env:PATH
|
||
|
||
& 'C:\Program Files\xmake\xmake.exe' f -c -p windows -a x64 -m release -y
|
||
& 'C:\Program Files\xmake\xmake.exe' build Frostbite2DWindowsSmoke
|
||
```
|
||
|
||
产物:
|
||
|
||
```text
|
||
build\windows\x64\release\Frostbite2DWindowsSmoke.exe
|
||
```
|
||
|
||
运行 EXE 时,需要把依赖 DLL 放在 EXE 同目录。当前已验证至少需要:
|
||
|
||
```text
|
||
SDL2.dll
|
||
SDL2_image.dll
|
||
SDL2_mixer.dll
|
||
SDL2_ttf.dll
|
||
FLAC.dll
|
||
```
|
||
|
||
如果重新清理构建目录后 DLL 丢失,可以从 XMake 包缓存复制。当前机器路径示例:
|
||
|
||
```powershell
|
||
$out='build\windows\x64\release'
|
||
|
||
Copy-Item 'C:\Users\11655\AppData\Local\.xmake\packages\l\libsdl2\2.32.10\9cf157962d784bab85f45cbb66d68046\bin\SDL2.dll' $out -Force
|
||
Copy-Item 'C:\Users\11655\AppData\Local\.xmake\packages\l\libsdl2_image\2.8.8\026ef5efba044dc0824fc0125a4307c9\bin\SDL2_image.dll' $out -Force
|
||
Copy-Item 'C:\Users\11655\AppData\Local\.xmake\packages\l\libsdl2_mixer\2.8.1\03da77434a3f43dfa9c6e52b7ea5dafd\bin\SDL2_mixer.dll' $out -Force
|
||
Copy-Item 'C:\Users\11655\AppData\Local\.xmake\packages\l\libsdl2_ttf\2.24.0\56f7684f28e04a3eb194f8f4a4ed4c2b\bin\SDL2_ttf.dll' $out -Force
|
||
Copy-Item 'C:\Users\11655\AppData\Local\.xmake\packages\l\libflac\1.5.0\96b3cdc9f5834a3c9ac2a033627c794b\bin\FLAC.dll' $out -Force
|
||
```
|
||
|
||
运行测试:
|
||
|
||
```powershell
|
||
& build\windows\x64\release\Frostbite2DWindowsSmoke.exe
|
||
```
|
||
|
||
正常输出中应包含:
|
||
|
||
```text
|
||
Frostbite2D Windows smoke init ok.
|
||
Renderer initialized
|
||
TaskSystem initialized
|
||
Application stopped
|
||
```
|
||
|
||
## 2. Nintendo Switch 编译
|
||
|
||
### 2.1 前置环境
|
||
|
||
当前机器已验证可用:
|
||
|
||
- devkitPro:`C:\devkitPro`
|
||
- devkitA64:`C:\devkitPro\devkitA64`
|
||
- libnx:`C:\devkitPro\libnx`
|
||
- Switch portlibs:`C:\devkitPro\portlibs\switch`
|
||
- XMake:`C:\Program Files\xmake\xmake.exe`
|
||
|
||
Switch 版依赖不走 XMake 的桌面包,而是使用 devkitPro 的 portlibs:
|
||
|
||
- SDL2
|
||
- SDL2_image
|
||
- SDL2_mixer
|
||
- SDL2_ttf
|
||
- GLM
|
||
- zlib
|
||
- HarfBuzz
|
||
- bzip2
|
||
- libnx
|
||
|
||
### 2.2 编译 Switch 引擎静态库
|
||
|
||
```powershell
|
||
$env:PATH='C:\devkitPro\devkitA64\bin;C:\devkitPro\tools\bin;C:\devkitPro\msys2\usr\bin;C:\Program Files\CMake\bin;C:\Program Files\xmake;' + $env:PATH
|
||
$env:DEVKITPRO='C:\devkitPro'
|
||
$env:DEVKITA64='C:\devkitPro\devkitA64'
|
||
|
||
& 'C:\Program Files\xmake\xmake.exe' f -c -p switch -a aarch64 -m release --toolchain=cross --sdk='C:\devkitPro\devkitA64' --bin='C:\devkitPro\devkitA64\bin' --cross='aarch64-none-elf-' -y
|
||
& 'C:\Program Files\xmake\xmake.exe' build Frostbite2D
|
||
```
|
||
|
||
产物:
|
||
|
||
```text
|
||
build\switch\aarch64\release\libFrostbite2D.a
|
||
```
|
||
|
||
### 2.3 编译 Switch NRO 测试程序
|
||
|
||
项目内有一个最小 Switch 测试程序:
|
||
|
||
```text
|
||
examples\switch_smoke\main.cpp
|
||
```
|
||
|
||
它会调用:
|
||
|
||
```cpp
|
||
frostbite2D::switchInit();
|
||
frostbite2D::switchShutdown();
|
||
```
|
||
|
||
先确保 `libFrostbite2D.a` 已经生成,然后执行:
|
||
|
||
```powershell
|
||
$env:PATH='C:\devkitPro\devkitA64\bin;C:\devkitPro\tools\bin;C:\devkitPro\msys2\usr\bin;' + $env:PATH
|
||
$env:DEVKITPRO='C:\devkitPro'
|
||
$env:DEVKITA64='C:\devkitPro\devkitA64'
|
||
|
||
$out='build\switch\aarch64\release\switch_smoke'
|
||
New-Item -ItemType Directory -Force -Path $out | Out-Null
|
||
|
||
$common=@(
|
||
'-g',
|
||
'-O2',
|
||
'-D__SWITCH__',
|
||
'-march=armv8-a+crc+crypto',
|
||
'-mtune=cortex-a57',
|
||
'-mtp=soft',
|
||
'-ffunction-sections',
|
||
'-fdata-sections',
|
||
'-fPIE',
|
||
'-IFrostbite2D\include',
|
||
'-IFrostbite2D\third_party\quickjspp',
|
||
'-IC:\devkitPro\libnx\include',
|
||
'-IC:\devkitPro\portlibs\switch\include',
|
||
'-IC:\devkitPro\portlibs\switch\include\SDL2',
|
||
'-specs=C:\devkitPro\libnx\switch.specs'
|
||
)
|
||
|
||
$compileArgs=@('-c','-std=c++17') + $common + @(
|
||
'-o', "$out\main.o",
|
||
'examples\switch_smoke\main.cpp'
|
||
)
|
||
& C:\devkitPro\devkitA64\bin\aarch64-none-elf-g++.exe @compileArgs
|
||
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||
|
||
$linkArgs=@(
|
||
'-specs=C:\devkitPro\libnx\switch.specs',
|
||
'-g',
|
||
'-march=armv8-a+crc+crypto',
|
||
'-mtune=cortex-a57',
|
||
'-mtp=soft',
|
||
'-fPIE',
|
||
'-Lbuild\switch\aarch64\release',
|
||
'-LC:\devkitPro\libnx\lib',
|
||
'-o', "$out\Frostbite2D_smoke.elf",
|
||
"$out\main.o",
|
||
'-lFrostbite2D',
|
||
'-lnx'
|
||
)
|
||
& C:\devkitPro\devkitA64\bin\aarch64-none-elf-g++.exe @linkArgs
|
||
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||
|
||
& C:\devkitPro\tools\bin\nacptool.exe --create 'Frostbite2D Smoke' 'Frostbite2D' '1.0.0' "$out\control.nacp"
|
||
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||
|
||
& C:\devkitPro\tools\bin\elf2nro.exe "$out\Frostbite2D_smoke.elf" "$out\Frostbite2D_smoke_meta.nro" --nacp="$out\control.nacp" --icon=C:\devkitPro\libnx\default_icon.jpg
|
||
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||
```
|
||
|
||
产物:
|
||
|
||
```text
|
||
build\switch\aarch64\release\switch_smoke\Frostbite2D_smoke.elf
|
||
build\switch\aarch64\release\switch_smoke\Frostbite2D_smoke_meta.nro
|
||
build\switch\aarch64\release\switch_smoke\control.nacp
|
||
```
|
||
|
||
推荐运行带元数据的版本:
|
||
|
||
```text
|
||
Frostbite2D_smoke_meta.nro
|
||
```
|
||
|
||
不带 NACP/icon 的 NRO 在 Ryujinx 1.3.3 中可能触发 `OpenNroAssetSection` 相关加载错误。
|
||
|
||
正常运行后屏幕显示:
|
||
|
||
```text
|
||
Frostbite2D Switch smoke test
|
||
Press PLUS to exit.
|
||
```
|
||
|
||
### 2.4 编译 Switch 游戏框架 NRO
|
||
|
||
当前游戏框架已经接入 Switch 构建目标:
|
||
|
||
```text
|
||
Frostbite2DGameSwitch
|
||
```
|
||
|
||
该目标和 Windows 共用:
|
||
|
||
```text
|
||
game\src\main.cpp
|
||
```
|
||
|
||
入口内部通过 `__SWITCH__` 编译分支处理平台差异,运行同一套
|
||
`WhiteboxScene`、`StageRenderer`、`DebugOverlay`、`PlayerActor` 和
|
||
`LevelDefinition` 游戏框架。
|
||
|
||
构建命令:
|
||
|
||
```powershell
|
||
$env:PATH='C:\devkitPro\devkitA64\bin;C:\devkitPro\tools\bin;C:\devkitPro\msys2\usr\bin;C:\Program Files\CMake\bin;C:\Program Files\xmake;' + $env:PATH
|
||
$env:DEVKITPRO='C:\devkitPro'
|
||
$env:DEVKITA64='C:\devkitPro\devkitA64'
|
||
|
||
& 'C:\Program Files\xmake\xmake.exe' f -c -p switch -a aarch64 -m release --toolchain=cross --sdk='C:\devkitPro\devkitA64' --bin='C:\devkitPro\devkitA64\bin' --cross='aarch64-none-elf-' -y
|
||
& 'C:\Program Files\xmake\xmake.exe' -b Frostbite2DGameSwitch
|
||
```
|
||
|
||
产物:
|
||
|
||
```text
|
||
build\switch\aarch64\release\Frostbite2DGame.elf
|
||
build\switch\aarch64\release\switch_game\NSUnknownGame.nro
|
||
build\switch\aarch64\release\switch_game\control.nacp
|
||
build\switch\aarch64\release\switch_game\assets\
|
||
```
|
||
|
||
`xmake.lua` 会在构建后自动:
|
||
|
||
- 复制 `game\assets` 到 `build\switch\aarch64\release\switch_game\assets`
|
||
- 生成 `control.nacp`
|
||
- 调用 `elf2nro` 生成带元数据的 `NSUnknownGame.nro`
|
||
- 将 `game\assets` 复制到临时 `romfs\assets` 后内嵌到 NRO 中,因此运行时可以直接读取
|
||
`romfs:/assets/...`
|
||
|
||
Switch 运行时资源目录当前优先由引擎解析为:
|
||
|
||
```text
|
||
romfs:/assets
|
||
```
|
||
|
||
如果 RomFS 挂载失败,才会回退到:
|
||
|
||
```text
|
||
/switch/Frostbite2D/NS Unknown Game/assets
|
||
```
|
||
|
||
构建输出目录中的 `switch_game\assets` 是调试和外部部署用的资源副本。
|
||
|
||
当前已验证:
|
||
|
||
- `Frostbite2DGameSwitch` 可成功编译为 ELF/NRO
|
||
- PC 和 Switch 共用同一套 GLES 300 es shader
|
||
- Windows 游戏目标仍可正常编译和启动
|
||
- devkitPro 当前版本的 `SDL2_ttf` / `freetype` 需要静态链接 `harfbuzz` 和 `bz2`,该链接项已写入 `engine.lua`
|
||
|
||
## 3. 常见问题
|
||
|
||
### 3.1 切换平台后编译异常
|
||
|
||
XMake 会缓存当前平台配置。Windows 和 Switch 来回切换时,建议使用 `f -c` 重新配置:
|
||
|
||
```powershell
|
||
& 'C:\Program Files\xmake\xmake.exe' f -c -p windows -a x64 -m release -y
|
||
```
|
||
|
||
或:
|
||
|
||
```powershell
|
||
& 'C:\Program Files\xmake\xmake.exe' f -c -p switch -a aarch64 -m release --toolchain=cross --sdk='C:\devkitPro\devkitA64' --bin='C:\devkitPro\devkitA64\bin' --cross='aarch64-none-elf-' -y
|
||
```
|
||
|
||
### 3.2 Windows EXE 启动时报 `0xC0000135`
|
||
|
||
这是缺 DLL。把 SDL 相关 DLL 复制到 EXE 同目录即可。
|
||
|
||
### 3.3 Switch NRO 在 Ryujinx 中加载失败
|
||
|
||
优先使用带 NACP/icon 的:
|
||
|
||
```text
|
||
Frostbite2D_smoke_meta.nro
|
||
```
|
||
|
||
不要优先使用裸的 `Frostbite2D_smoke.nro`。
|
||
|
||
### 3.4 Switch 游戏 NRO 启动后资源加载失败或黑屏
|
||
|
||
优先确认 `NSUnknownGame.nro` 是新构建的 RomFS 版本。构建时 `elf2nro`
|
||
命令应包含:
|
||
|
||
```text
|
||
--romfsdir=<build>\switch_game\romfs
|
||
```
|
||
|
||
NRO 内部应能访问:
|
||
|
||
```text
|
||
romfs:/assets/shaders/shaders.json
|
||
romfs:/assets/shaders/sprite.vert
|
||
romfs:/assets/shaders/sprite.frag
|
||
romfs:/assets/shaders/colored_quad.vert
|
||
romfs:/assets/shaders/colored_quad.frag
|
||
romfs:/assets/character/male/*.png
|
||
```
|
||
|
||
旧版本曾只把资源复制到 NRO 旁边,运行时引擎找不到 shader 和纹理,
|
||
会表现为黑屏或没有场景内容。
|
||
|
||
### 3.5 Switch 链接时报 `hb_*` 或 `BZ2_*` 未定义
|
||
|
||
这是 devkitPro portlibs 静态库依赖未完整链接。当前 `engine.lua` 已把
|
||
`harfbuzz` 和 `bz2` 加入 Switch 链接列表;如果换机器后再次出现,先确认:
|
||
|
||
```powershell
|
||
Test-Path C:\devkitPro\portlibs\switch\lib\libharfbuzz.a
|
||
Test-Path C:\devkitPro\portlibs\switch\lib\libbz2.a
|
||
```
|