<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Eden on Time Friend</title><link>https://time-friend.com/zh/tags/eden/</link><description>Recent content in Eden on Time Friend</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Thu, 24 Sep 2026 14:00:00 +0000</lastBuildDate><atom:link href="https://time-friend.com/zh/tags/eden/index.xml" rel="self" type="application/rss+xml"/><item><title>骁龙 8 Gen 2 掌机跑 Switch 模拟器: 内存布局越大越不稳, 以及显存优化实测</title><link>https://time-friend.com/zh/archive/switch-emulation-snapdragon-tuning/</link><pubDate>Thu, 24 Sep 2026 14:00:00 +0000</pubDate><guid>https://time-friend.com/zh/archive/switch-emulation-snapdragon-tuning/</guid><description>&lt;p&gt;我的 AYN Thor 掌机用的是骁龙 8 Gen 2, 平时靠 Eden 玩 Switch。有一段时间《王国之泪》总是&amp;quot;退后台&amp;quot;或者干脆闪退, 稳定版和 nightly 两个构建都一样。我第一反应是内存不够——掌机有 15GB 内存, 那 Eden 的内存布局就该往大了给, 于是我把它从默认调到最高的 8GB。结果问题变得更频繁了。&lt;/p&gt;
&lt;p&gt;这篇就是从这个反直觉的结果往回查的过程。&lt;/p&gt;
&lt;h2 id="退后台和闪退-是两个独立的问题"&gt;退后台和闪退, 是两个独立的问题&lt;/h2&gt;
&lt;p&gt;一开始我把两个现象当成一件事, 后来看日志才发现根因完全不同。判断办法很简单: 看 Eden 进程还在不在。退后台的时候进程活着, 只是它的 &lt;code&gt;EmulationActivity&lt;/code&gt; 被停掉了; 闪退的时候进程直接没了, 留下 tombstone。&lt;/p&gt;


&lt;div class="mermaid-wrap"&gt;
&lt;pre class="mermaid" role="img" aria-label="Mermaid diagram"&gt;flowchart TB
 A[&amp;#34;游戏退后台或闪退&amp;#34;] --&amp;gt; B{&amp;#34;Eden 进程还在吗&amp;#34;}
 B --&amp;gt;|&amp;#34;进程在, 被顶到后台&amp;#34;| C[&amp;#34;lmkd 内存压力&amp;lt;br/&amp;gt;杀掉 iiSU 桌面&amp;lt;br/&amp;gt;桌面重启抢占前台&amp;#34;]
 B --&amp;gt;|&amp;#34;进程消失&amp;#34;| D[&amp;#34;GPU 管线崩溃&amp;lt;br/&amp;gt;着色器缓存与当前驱动不匹配&amp;#34;]
 C --&amp;gt; E[&amp;#34;内存布局 8GB → 6GB → 4GB&amp;#34;]
 D --&amp;gt; F[&amp;#34;删除驱动专属的着色器缓存&amp;lt;br/&amp;gt;确认加载的是 Turnip&amp;#34;]&lt;/pre&gt;
&lt;/div&gt;


&lt;script type="module"&gt;
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
mermaid.initialize({
 startOnLoad: false,
 theme: 'base',
 themeVariables: {
 background: '#1d1f21',
 primaryColor: '#282c34',
 primaryBorderColor: '#3e4147',
 primaryTextColor: '#c9cacc',
 lineColor: '#5a5f66',
 edgeLabelBackground: '#1d1f21'
 }
});
mermaid.run({ querySelector: 'pre.mermaid' });
&lt;/script&gt;


&lt;p&gt;分开之后, 每个问题都有了明确的证据链。&lt;/p&gt;</description></item><item><title>Eden 稳定版和 nightly 的存档为什么对不上: 用户档案 ID 与 UID 字节逆序</title><link>https://time-friend.com/zh/archive/eden-nightly-save-migration-profile-id/</link><pubDate>Sun, 20 Sep 2026 10:00:00 +0000</pubDate><guid>https://time-friend.com/zh/archive/eden-nightly-save-migration-profile-id/</guid><description>&lt;p&gt;我把 Eden 的主力版本从稳定版换成了 nightly。它和稳定版包名不同, 可以直接共存, 游戏也都能正常打开。但进去之后, 之前所有的存档一个都读不到, 每个游戏都像第一次玩。我第一反应是 nightly 把数据目录清了, 或者存档被覆盖了, 赶紧去翻文件。&lt;/p&gt;
&lt;p&gt;文件都在。少的不是存档, 是 nightly 去错了地方找。&lt;/p&gt;
&lt;h2 id="两个构建共用游戏-但不共用用户档案"&gt;两个构建共用游戏, 但不共用用户档案&lt;/h2&gt;
&lt;p&gt;Eden 把 Switch 的存档放在数据目录的 &lt;code&gt;nand/user/save/&lt;/code&gt; 下。这条路径不是只有一层, 它的结构大致是 &lt;code&gt;nand/user/save/0000000000000000/&amp;lt;用户档案ID&amp;gt;/&amp;lt;TitleID&amp;gt;/&lt;/code&gt;, 中间那层是&lt;strong&gt;用户档案&lt;/strong&gt;。稳定版和 nightly 是两个独立安装的应用, 各自的数据目录分开, 更关键的是: &lt;strong&gt;nightly 首次启动时会自己生成一个新的用户档案 ID&lt;/strong&gt;, 和稳定版那个没有任何关系。&lt;/p&gt;
&lt;p&gt;我这边稳定版的活动档案是 &lt;code&gt;D2AE7D815565D5C93F432C7C74A7DD6A&lt;/code&gt;, nightly 自动生成的是 &lt;code&gt;173CB8FB1F16348366B4CABB88A445D9&lt;/code&gt;。存档文件都在 nightly 的数据目录里(从稳定版拷过来之后), 但 nightly 只会去它自己那个活动档案目录里找游戏存档, 于是看不到。&lt;/p&gt;
&lt;h2 id="存档目录名从哪来"&gt;存档目录名从哪来&lt;/h2&gt;
&lt;p&gt;那个看起来像随机十六进制串的档案目录名, 其实不是随机的。日志里能观察到, 它来自用户档案的 UID, 并且是 UID 的&lt;strong&gt;字节逆序&lt;/strong&gt;排列——同一段身份数据, 换个字节序就成了目录名。两个构建只要各自生成了新 UID, 目录名就必然不同, 这也是为什么换构建、甚至 nightly 自己重新初始化之后, 存档会&amp;quot;对不上&amp;quot;。理解了这一点, 就不会再把它当成文件损坏。&lt;/p&gt;
&lt;h2 id="为什么直接拷存档会失效"&gt;为什么直接拷存档会失效&lt;/h2&gt;
&lt;p&gt;最容易踩的坑是: 把稳定版的 &lt;code&gt;save/&lt;/code&gt; 整个拷到 nightly 的 &lt;code&gt;save/&lt;/code&gt;, 以为就完事了。结果 nightly 里依然读不到。原因是稳定版拷贝过去的目录名是 &lt;code&gt;D2AE7D...&lt;/code&gt;, 而 nightly 的活动档案是 &lt;code&gt;173CB8FB...&lt;/code&gt;, 内容进了库, 但没进 nightly 真正会查的那个抽屉。所以迁移必须做&lt;strong&gt;两段覆盖&lt;/strong&gt;: 先把稳定版的存档根整体带过来, 再把稳定版活动档案里的内容, 再拷进 nightly 的活动档案目录。&lt;/p&gt;</description></item><item><title>Eden 模拟器配置每次崩溃就被重置: 从 C++ 源码的非原子写入讲起</title><link>https://time-friend.com/zh/archive/eden-config-reset-non-atomic-write/</link><pubDate>Sat, 05 Sep 2026 10:00:00 +0000</pubDate><guid>https://time-friend.com/zh/archive/eden-config-reset-non-atomic-write/</guid><description>&lt;p&gt;Eden 里的设置总是莫名其妙回到默认, 尤其在我把模拟器强杀、或者它自己崩溃之后。图形驱动、内存布局、语言区域, 全部复位。我一开始以为是 Android 什么时候把应用数据清了, 先后重装过两次, 还在手机上给它开了各种后台保活。重装能好一阵, 然后又犯。&lt;/p&gt;
&lt;p&gt;真正的原因和 Android 没关系, 在 Eden 自己的源码里。&lt;/p&gt;
&lt;h2 id="不是没保存-是保存到一半被截断"&gt;不是&amp;quot;没保存&amp;quot;, 是&amp;quot;保存到一半被截断&amp;quot;&lt;/h2&gt;
&lt;p&gt;配置存在 &lt;code&gt;files/config/config.ini&lt;/code&gt;。Eden 保存设置的写法, 是把整个文件重新写一遍。问题在打开文件的模式上:&lt;/p&gt;


&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; Config&lt;span style="color:#f92672"&gt;::&lt;/span&gt;WriteToIni() &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; fp &lt;span style="color:#f92672"&gt;=&lt;/span&gt; fopen(config_loc.c_str(), &lt;span style="color:#e6db74"&gt;&amp;#34;wb&amp;#34;&lt;/span&gt;); &lt;span style="color:#75715e"&gt;// &amp;#34;wb&amp;#34; 一打开就把文件截断为 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; config&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;Save(writer, false); &lt;span style="color:#75715e"&gt;// 再逐项写入；若此刻崩溃 → 文件残缺
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; Config&lt;span style="color:#f92672"&gt;::&lt;/span&gt;Reload() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ReadValues(); &lt;span style="color:#75715e"&gt;// 读现有配置
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; SaveValues(); &lt;span style="color:#75715e"&gt;// 立刻又写回去
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;&amp;quot;wb&amp;quot;&lt;/code&gt; 这个模式在 POSIX 里的语义是: 打开即把文件截断成 0 字节, 然后从零开始写。也就是说, 从打开到写完的这段时间里, 磁盘上的 &lt;code&gt;config.ini&lt;/code&gt; 处于&amp;quot;已经被清空、还没写回来&amp;quot;的状态。如果在这段窗口里进程被强杀或崩溃, 留下的就是一个残缺或空白的文件。下一次启动去解析它, 解析失败, Eden 就回退到内置默认值——看到的现象就是&amp;quot;配置被重置&amp;quot;。&lt;/p&gt;
&lt;p&gt;这还没完。&lt;code&gt;Reload()&lt;/code&gt; 每次启动都会先读、再立刻写回去。也就是说每次启动都有一个这样的写入窗口, 崩溃并不需要多罕见。写配置本身不是原子的(没有先写临时文件再 &lt;code&gt;rename&lt;/code&gt;), 这是根因。&lt;/p&gt;</description></item></channel></rss>