准备

平台环境

注意 示例程序最大化地使用了 YSLib 的平台模拟特性,支持特定的目标平台在运行时作为宿主平台对另一平台的平台模拟,即运行的原生示例程序和被模拟平台的原生程序保持基本相同的功能效果;但并不保证所有其它 YSLib 程序同样支持。

  被正式支持的平台模拟列表如下:

  • PC 模拟 DS

  被非正式支持的平台模拟列表如下:

  • Android 模拟 DS

硬件资源要求

  占用的硬件资源不确定,取决于平台配置以及具体应用程序。

注意 特定平台可能有额外限制,详见各个平台运行时环境的说明。

文件系统

  为最大化可移植性,原则上 YSLib 的程序逻辑不依赖自身组件具有显式编码的具体文件路径,因此默认不要求在具体系统约定的周知(well-known) 的文件系统位置(如 Windows DLL 搜索路径中的目录和 [FHS](https://zh.wikipedia.org/zh-cn/%E6%96%87%E4%BB%B 6%E7%B3%BB%E7%BB%9F%E5%B1%82%E6%AC%A1%E7%BB%93%E6%9E%84%E6%A0%87%E5%87%86) 定义的目录)部署。但具体平台配置可以自行限定目录布局作为默认运行时环境,如 Sysroot 。其中外部文件可有默认路径,参见以下相关章节。

  YSLib 中的库使用的文件系统路径具有以下约束:

  • 不依赖兼容 POSIX 的文件系统和路径表示。
    • 特别地,不依赖文件系统是否具有文件名的大小写敏感性。
    • 推论 为保证可移植性,文件系统路径大小写敏感,需要显式区分而加以明确。
    • 这样仍可兼容 FAT 等大小写不敏感的文件系统。
  • 要求支持符合 YSLib 项目规范的开发(参见项目的 doc/ProjectRules.txt )。

  一般地, YBase 不要求文件系统访问;使用 YFramework 框架的程序,由 YFramework 中的框架初始化等逻辑引入文件系统访问。

二进制依赖项

  按以上文件路径约定,构建得到的目标程序没有预设特定的位置限制,可按需转移。

  运行程序前,应确保程序能找到二进制依赖项:

  • 确保先决条件中的依赖项可以在 PATH 环境变量的目录被找到,或者复制到程序所在的目录。
  • 对于静态链接 YFramework 和 YBase 程序,不需要其它二进制程序文件的部署。
  • 使用 DLL 的程序可能依赖 YFramework.dll 和 YBase.dll ,或者 debug 配置的 YFrameworkd.dll 和 YBased.dll 。这些库已经在 sysroot 的 bin 目录下安装,因此可以直接把 bin 目录加入 PATH 环境变量,而不必复制或移动库文件。

说明 在任意被支持的平台上,YSLib 避免使用导致在特定平台上被特殊处理且无法可靠避免这种行为而确保兼容性一致的外部依赖项名称(若因为外部环境更新导致此类问题,则需在 YSLib 的新版本适当修改后支持)。例如,支持 API Set Schema 的 Windows 版本加载 DLL 时,LdrLoadDll 解析以 api-EXT- 起始的文件名进行重定位 ,因此设计时确保外部依赖项对应的文件名不以这些前缀起始。

外部文件

  外部文件包括:

  • 在文件系统中部署的外部二进制依赖项。
  • 配置文件:可被修改以改变程序的运行时行为。
  • 其它数据文件。

  数据文件提供程序运行时所需的必要或可选的信息。配置文件可能作为数据文件使用。

  外部文件的路径应符合前述关于文件路径的约定。

文件格式

  除非另行指定,使用以下文件格式:

  • 配置文件是内容为 NPL 配置的 UTF-8 文本文件,具有 UTF-8 BOM
  • 其它数据文件为二进制文件

文件系统布局

  除配置文件可能指定默认的具体位置(详见下文)外,YFramework 程序的不需依赖特别的文件系统布局。

  除非另行指定(暂无),YFramework 不创建文件系统目录。

  Sysroot 提供类 UNIX 系统使用的布局作为可选项。

文件访问约定

  除非另行指定,YFramework 对外部文件的访问适用本节约定。

注意 除非另行指定,程序访问配置文件的时机是未指定的。

基本要求

  应确保外部文件满足以下条件,否则运行时出错,或在另行指定(暂无)的特定情形下不保证行为符合预期:

  • 具有适当的(可读和可写)权限以允许程序访问其内容及元数据,或在必要时进行创建。
  • 需要写入的文件所在的位置应该具有足够的空间。

文件映射和内存映像

  文件读写使用 YCLib::MemoryMapping ,优先使用内存文件映射。在文件无法访问时,部分文件可能使用内存映像代替。

注意 除非使用内存映像,应确保外部文件的内容可读;否则,可在之后引发无法恢复的错误;参见当前实现使用的 YCLib::MemoryMapping 的注意事项

共享文件

  宿主平台使用协同锁(advisory lock) 对并发文件内容访问提供有限的共享保护,避免基于 YFramework 程序并发访问外部文件时的竞争。不使用强制锁(mandatory lock) 以利于提升性能。

注意 除检查文件创建外,不提供相关文件系统元数据并发访问保护。

注意 因为锁定非强制,宿主不保证其它机制访问文件的程序(如非 YFramework 程序)在这里产生冲突,有可能破坏文件内容。用户应避免对相关文件造成此类访问的破坏性编辑。

注意 因为访问顺序未指定,不同 YFramework 实例可能修改相同的文件(如配置文件)而导致外部可见的影响。

  未来可能添加完整的对共享文件内容修改的传递和检查的机制。

配置生成和输入输出

  配置文件可能提供默认内容,在外部文件不存在或读取失败时尝试创建。默认内容一般由框架直接提供。

  • 自动生成并保存外部文件时需确保程序可在指定目录下创建文件。
    • 具体目录视具体文件而定。
    • 可在运行前部署正确的配置文件以避免自动生成。
  • 若无法满足,生成保存在内存中的临时配置映像之后的修改不会保存到外部文件。
    • 注意 某些版本的 Windows (如 Windows Vista 以后的版本)在特定的目录(如 %PROGRAMFILES% )中创建文件默认需要管理员权限。

公共配置文件

  文件 yconf.txt 为 YFramework 程序的公共配置文件,在框架初始化时,先于其它配置文件之前处理。若不存在,提供默认内容。其位置是预先指定的,和平台相关。详见下一章对框架初始化的说明。

  为避免 YFramework 程序在运行时出错或行为不符合预期,注意确保满足前述访问约定的要求。若无法在程序映像文件所在目录(详见以下关于框架初始化的说明)创建文件,配置不能保存到外部文件。

  在 Win32 上一个正确的公共配置文件的内容可能是这样的:

YFramework 
(
	DataDirectory "C:\Data\\"
)
(
	FontDirectory "C:\Windows\Font\\"
)
(
	FontFile "C:\Windows\Font\FZYTK.TTF"
)

  这里指定的路径分别为数据目录路径、字体文件目录路径和字体文件路径。

数据目录

  用于存放 YFramework 程序必要的数据以及运行时的配置。

  通过 yconf.txt 中项 DataDirectory 的值指定数据目录的路径。

  自动生成的配置中数据目录的默认路径如下:

  • DS : /Data 目录
  • Win32 :同默认生成配置文件所在的目录
  • Android : SD 卡目录(自动检测同上)下的 Data 目录
  • 其它平台:当前工作目录

  当前可用数据文件位于 YSLib 项目的 /Data 下,可自行复制到数据目录。

CHRLib 的 GBK 转换例程初始化

  对使用 CHRLib 提供的 GBK 编码转换的程序,需保证数据目录下存在数据文件 cp113.bin

  对 Win32 平台, CHRLib 初始化 GBK 转换例程读取数据文件失败时,首先尝试使用 NLS 替代:

  • 通过读取注册表取得 NLS 文件路径,默认为系统目录下的 C_936.NLS
  • 注意 并非所有 Windows 安装带有指定的 NLS 文件。例如,某些版本的 64 位 Windows 10 可能在 %windir%\system32\C_936.NLS 但不存在 %windir\SysWOW64\C_936.NLS 。由于 64 位 Windows 默认对系统目录重定向,导致 32 位的 YFramework 初始化找不到注册表指定的默认 NLS 文件。当前不特别处理这种情况,因此 NLS 不可用。
  • 若 Win32 NLS 初始化仍然失败,则 CHRLib 初始化 GBK 转换例程失败。

  对其它平台,数据文件读取失败则 CHRLib 初始化 GBK 转换例程失败。

  初始化失败后,使用 CHRLib 转换 GBK 编码的程序在调用转换例程时抛出异常,可能导致程序非正常退出。

MIME 数据

  数据目录下的配置文件 MIMEExtMap.txt 存储 MIME 数据。若不存在,提供默认内容。

字体目录和文件路径

  只要其中之一有效即可(若没有成功指定字体文件路径,则默认字体文件路径不确定)。

  自动生成的配置中字体文件的默认路径如下:

  • DS : /Font/FZYTK.ttf
  • Win32 :系统字体目录下的 SimSun.ttc
  • Android : /system/fonts/DroidSansFallback.ttf
  • Linux : ./SimSun.ttc

  自动生成的配置中字体目录的默认路径如下:

  • DS : /Font 目录
  • Android : /system/fonts 目录
  • 其它平台:同数据目录

特定平台运行环境

DS

  以下说明中, $NDSEmulator 为模拟器 DeSmuME 可执行文件的绝对路径, $TargetPath 为 ROM 映像文件( .nds 文件)的路径, $FAT_Path为 FAT 目录路径(见以下说明)。

  之前经测试的最小版本为 0.9.6 。建议使用最新版本。

  运行时,需在运行模拟器的宿主机中准备一个目录作为映射到设备中的虚拟 FAT 目录。宿主的目录在运行中不会被 DeSmuME 修改;宿主目录的文件系统不要求为 FAT 。运行时会加载虚拟目录的内容。

注意 官方版的 DeSmuME 不支持包含非 ASCII 字符的宿主路径而忽略这些文件。部分修改版可能没有这个限制。

注意 因为 DS 模拟器和烧录卡需要加载 ROM 映像到 RAM 后才能运行,映像大小会影响可用运行内存,使用 debug 配置构建的 YSTest 示例版本不一定在 DS 上支持所有功能。相关支持限制及变更详见 YSLib 项目文档 doc/Test.txt

  可通过以下方式之一指定 FAT 目录。

Slot 1 映射

  Slot 1 (即 NDS ROM 卡槽,硬件介质可以是 NDS 卡带,或烧录卡和存储卡的组合)的模拟从 DeSmuME 0.9.8 版本起支持。

  运行命令行示例:

"$NDSEmulator" "$TargetPath" --preload-rom --slot1-fat-dir="$FAT_Path"

  其中 --preload-rom 对 0.9.10 和 0.9.11 版本是必须的(以支持自动 DLDI(en-US) 补丁),否则加载失败。这个选项可以在模拟器(Windows 版本)的 GUI 菜单中 ConfigROM Loading 中选择。最新版本的源码会对自制 ROM 自动启用 ROM 预先加载的选项而不用另行配置,可以省略这个选项。

Slot 2 映射

  Slot 1 (即 GBA ROM 卡槽,硬件介质可以是 GBA 卡带或其它扩展)的模拟需要配置为使用 GBA Movie Player (Compact Flash)

  运行命令行示例:

"$NDSEmulator" "$TargetPath" --cflash-path="$FAT_Path"

  对 0.9.10 和 0.9.11 版本,需同 Slot 1 映射添加 --preload-rom 或使用菜单设置加载选项,否则同样无法加载(尽管源码中表示 --preload-rom 是适用 Slot 1 而不是 Slot 2 的选项)。

  这个选项也可以通过 GUI 配置。在 0.9.9 版本前,使用菜单 EmulationGBA Slot 。自 0.9.9 版本起,使用菜单 ConfigSlot 2 (GBA Slot)

注意 DeSmuME svn4030 及之后的一些版本(至少包括 0.9.8 )会在载入 MPCF 映像时错误地忽略 --cflash-path 选项,以 仿真(Emulation) → GBA 插槽(GBA Slot) 菜单中的设置或对应配置文件 desmume.ini 中指定正确的路径。

  在 desmume.ini 中有效的最小配置:

[GBAslot]
type=1
[GBAslot.CFlash]
fileMode=0
path=H:\NDS\efsroot\

  这里 H:\NDS\efsroot$FAT_Path 的一个示例。

注意 自 Slot1 0.9.10 起,当 Slot 1 设置为 R4 时会覆盖 Slot 2 设置加载 R4 路径( Dev+ 版本显示自动 DLDI 补丁在 Slot 1 设置为 R4 从 GBA Movie Player (Compact Flash) 改为 R4(DS) - Revolution for DS ),因此需确保Slot 1 设置不为 R4 ,或正确设置了 Slot 1 R4 的路径(而改用 Slot 1 映射)。

MinGW32

  自 build 431 起,YFramework 使用的 FreeImage 修改版集成 libjepg-turbo ,需要 CPU 支持 SSE2 指令集扩展。

  除 2005 年前生产的硬件外绝大多数环境已经满足这个条件。当前几乎所有兼容 IA-32 的市售 CPU 都包含 SSE2 支持。特别地,支持 x86_64 指令集的 CPU 要求支持 SSE2 ,在使用 x86_64 的 64 位 Windows 上运行 32 位 Win32 程序(通过 WoW64 )也支持 SSE2 。

Android

  可使用 adb 命令安装 APK 包,如:

"$ANDROID_SDK/platform-tools/adb" -e install -r "$1"

  此处 -e 指定 TCP/IP 设备(通常是模拟器),若使用 USB 设备(通常是物理机器)应移除或使用较新的 adb-d 选项代替; "$1" 指定 APK 文件路径。

  之后,在 Android 的 GUI 环境下直接运行安装的程序。

  若因签名变更等原因无法覆盖安装或更新,需要先卸载后再安装。

注意 Android 安装 .apk 包时需要占用额外存储资源。为避免内置存储空间不足导致不直接表现安装失败(需要 logcat 查看)但直至运行时找不到二进制库而导致启动失败,应保留足够的空间,特别是对占用较大的 debug 配置构建的映像。保留空间的大小一般大于 .apk 作为 .zip 解压缩占用的空间。另见此处报告的未确认的类似问题

框架初始化

  框架初始化服务于整个框架。

  初始化的重要策略之一是在程序启动时减少不必要的初始化,以允许实现以下目的:

  • 减少可能的外部依赖(如不需要使用文字的程序就不初始化字体缓存,也不需要依赖外部字体文件和字体配置等)。
  • 减少可能的运行时程序资源占用。
  • 保留静态链接时优化去除没有调用的代码以减少二进制可执行文件大小的可能性。

  按当前框架的设计,框架初始化在 DS 平台在程序运行初始阶段完成。其它平台可延迟初始化,按需调用。

  并非所有 YFramework 中的 API 都要求框架初始化。以下功能隐含自动进行的框架初始化:

  • 使用默认字体缓存。
  • 使用 MIME 数据时。

  框架初始化加载配置文件,其中配置文件路径的确定方式参见以下节的说明。成功公共加载配置文件后,框架初始化检查配置文件的内容,并访问框架公共配置。若检查失败,抛出异常。

  修改 YFramework 模块 Helper::Initialization 重新编译后,可修改默认设置改变初始化行为。以下行为可能会在未来改变

根路径

  **根路径(root path)**是框架初始化时参考的基本路径,由如下方式确定:

  • Win32 和 Linux(除 Android ):程序映像所在的目录。
  • Android :SD 卡目录(自动按顺序检测 /sdcard/mnt/sdcard/storage/sdcard0 之一)。
  • 其它平台:第一次初始化时的当前工作目录。

  确定根路径在框架初始化或要求确定根路径时进行。若定位程序映像,同时会解析符号链接。若定位根路径失败,抛出异常。

  抛出的异常默认不被框架处理,可使程序退出。用户代码捕获特定异常可改变默认退出行为。

配置路径

  公共配置文件 yconf.txt 所在目录的路径前缀(结尾带有路径分隔符)称为框架的配置路径(configuration path),决定和平台相关的配置加载起始位置。配置路径和配置文件相对路径(对 yconf.txt ,即配置文件名)组合得到配置文件路径。

  配置路径的确定方式和平台相关。

  任意平台总能确定一个首选的配置路径。

  除首选的配置路径外,一些平台还支持一个或多个不同的后备(fallback) 配置路径。在读写特定的配置文件时,若根路径访问失败,但存在后备配置路径,依序使用这些路径重试直至成功或全部访问失败。这样的配置文件当前包括 yconf.txt 。具体应用可使用初始化 API 以类似的方式加载其它配置文件。

  以下是具有后备配置路径的平台中确定配置路径的顺序:

  • Linux(除 Android ):
    • 首先使用首选的配置路径。
    • 若环境变量 HOME 非空,则路径 $HOME/.YSLib/ 是后备配置路径。
  • Win32 :在 Linux 的基础上:若 $HOME 非空,则路径 $HOME/.YSLib/ 是后备配置路径。
    • 同 Linux 平台的使用顺序(对应使用 Win32 的环境变量和路径语法,即备份路径 %HOME%\.YSLib\ )。
    • 若环境变量 USERPROFILE 非空,则路径 %USERPROFILE%\.YSLib\ 是后备配置路径。

  后备配置路径中若子目录 .YSLib 不存在则被创建。若创建失败,配置路径访问失败。

  对不具有后备路径的平台,首选的配置路径总是根路径。否则,首选的配置路径由以下方式确定:

  • 程序映像所在的位置可推断出符合类似 FHS 的文件系统布局(称为局部 FHS 目录布局),则首选的配置路径为程序映像所在的目录的上一级目录的 var 子目录下的 YSLib 子目录。
    • 推断文件系统布局为以 POSIX 环境变量语法表示为 $PREFIX/$PREFIX/$BIN/$PREFIX/lib/$PREFIX/share/ 这些路径前缀都存在且可作为目录访问,其中 $PREFIX 是程序映像所在的目录的上级目录,而 $BIN 是程序映像所在的目录的名称(按 FHS 通常为 bin ,此处不检查)。
    • 这保证创建映像的可执行程序映像的目录中内容不被修改,以符合 FHS 。
  • 否则,首选的配置路径为根路径。
    • 确定配置路径要求确定根路径。

  对不具有后备路径的平台不检查文件系统布局,也不要求实现确保程序映像路径的操作,以简化实现。

注意 若后备配置路径的配置文件可访问,直接使用此配置文件保存配置,不再创建配置文件。若需要恢复在首选配置路径创建配置文件的行为,需确保后备配置路径的配置文件不可访问(例如,移除所有后备配置路径的这些配置文件)。

配置文件加载

  加载配置文件 yconf.txt 时,首先按上述的顺序确定各个配置路径,每确定一个路径时访问其中的配置文件。若全部失败(如找不到可读的文件),则尝试自动生成配置并创建配置文件。创建配置文件的位置和顺序同上述确定配置路径的顺序。若创建配置文件全部失败,则放弃创建配置文件,直接使用生成的配置。

  不存在配置文件时,配置不能通过 Helper::Initialization 的 API 持久化保存,尝试保存配置会失败。

其它初始化

  成功后,框架进一步处理公共配置文件以外的其它初始化;详见以上具体配置文件的相关章节。