<!-- translated from docs/troubleshooting.md, sha256 dbe5760f150d -->
# 疑難排解

重新取得被鎖住的主機的控制權、常見問題、回報錯誤，以及開發者模式。

## 被鎖在外面？

PlayGuard 只能看到它所執行的那個系統的家長監護：**emuMMC 和 sysMMC 各有各的設定**（在其中一邊刪除的PIN碼，在另一邊仍然存在）。請在每個需要處理的系統上各執行一次。

### 二手主機

你知道PIN碼，但前一位主人的手機應用程式仍然連動著（解除連動失敗，或恢復原廠設定時要求輸入他的帳號）。

*安全 › 解除手機應用程式的連動*，接著，如果完全不想要家長監護，再選*刪除所有家長監護設定*。兩者都能離線使用，在 emuMMC 和 sysMMC 上都可以。

### 忘記PIN碼

*顯示PIN碼*本身就需要輸入PIN碼，所以在這裡幫不上忙。如果已安裝復原 sysmodule（見下文），放入一個 `RESCUE` 檔案後重新啟動：復原畫面會讓你設定新的PIN碼（它絕不會顯示舊的）。如果沒有安裝，*刪除所有家長監護設定*可以讓你從頭開始（會先儲存一份設定備份；備份絕不包含PIN碼）：如果*用PIN碼保護PlayGuard*已開啟（預設為*變更前*），請先把 SD 卡放進電腦，在 `sd:/config/playguard/config.json` 中把 `"pin_lock"` 設為 `"off"`。

### 遊玩時間限制封鎖了一切（0 分鐘上限），又忘了PIN碼

這時 PlayGuard 本身無法啟動。請**事先**安裝選用的復原 sysmodule（*主機 › 選用模組*，或手動安裝 `playguard-rescue.zip`）；被鎖住時，在 SD 卡上放一個空的 `config/playguard/RESCUE` 檔案再開機——它會解除主機的鎖定，讓 PlayGuard 可以開啟。請見 [`sysmodule/rescue/README.md`](https://github.com/JigSawFr/PlayGuard/blob/main/sysmodule/rescue/README.md)（英文）。

這個模組必須跟上 PlayGuard 的版本：每次更新 PlayGuard，都要重新解壓縮該版本的 `playguard-rescue.zip`（或在通知鈴鐺的*復原 sysmodule 不是最新版本*上選*更新*），然後重新啟動主機。舊版模組留下的報告 PlayGuard 無法驗證：這時復原畫面不會提供任何操作，只會說明模組版本較舊；在更新模組之前，再次使用 `RESCUE` 也會得到相同的結果。

### Homebrew 選單已鎖定

*主機 › 轉發器 › 鎖定自製軟體選單*會讓相簿和按住 R 啟動的遊戲不再開啟 Homebrew 選單。如果 PlayGuard 的轉發器和受保護的選單都不見了（在主機的「設定」中被刪除，或是在另一個系統上：鎖定寫在 SD 卡上，sysMMC 和 emuMMC 都會讀取）：

- **用電腦：** 刪除 SD 卡上的 `atmosphere/config/override_config.ini`（或放回 `config/playguard/override_config.ini.backup`，也就是原本的檔案），然後重新啟動主機。
- **已安裝復原 sysmodule 時**（選用）：在 SD 卡上放一個空的 `config/playguard/RESCUE` 檔案後重新啟動；sysmodule 會在開機時解除鎖定，PlayGuard 下次啟動時會說明。鎖定之後更新了 Atmosphère，也會以同樣的方式解除鎖定。

### 未改機的主機

PlayGuard 幫不上忙：它需要 Atmosphère。官方的做法是向任天堂客服申請主密鑰（master key）。

## 常見問題

### 剩餘時間沒有減少

剩餘時間大約 90 秒都沒有變化時，*今天*會顯示*主機目前沒有計算遊玩時間*。可能的原因：

- **網路時鐘從未設定過。** *主機 › 網路時鐘 › 測量時間差*，然後設定它（[網路時鐘](https://guard.boreale.dev/zh-hant/docs/features.md#網路時鐘)）。
- **時鐘被調回了。** 時鐘往回調之後，計時會停止，直到時鐘超過原本的時間；不需要做任何事。
- **剛寫入上限。** 啟動遊戲玩一分鐘後再查看。
- **家長監護已暫時解除。** 這時遊玩時間可能不會被計算：*今天 › 重新啟用*（或點一下標題列的膠囊標籤）。

### 上限自己改變了

- **手機應用程式仍然連動著。** 它下次同步會覆蓋 PlayGuard 設定的內容：*安全 › 解除手機應用程式的連動*。
- **其他工具，或設定檔。** 上限與 PlayGuard 上次看到的不同時，*今天*會顯示一張琥珀色的卡片，*紀錄 › 使用PlayGuard進行的變更*會列出在 PlayGuard 之外發現的每一項變更。在其中一項上按 Ⓐ 可以改回先前的值。
- **排定的設定檔**已套用，或在期間結束後改回（*遊玩時間限制 › 設定檔 › 排定的設定檔*）。

### 孩子玩超過了上限

- **主機只會提醒。** *遊玩時間限制 › 時間到時*：選擇*中斷軟體*。
- **家長監護一直處於解除狀態。** 解除期間，今天的上限會暫停：標題列的膠囊標籤會在每個分頁上顯示這一點，點一下它就會前往*今天 › 重新啟用*。重新啟動主機也會重新鎖定。
- **時鐘被調回了。** 計時會停止，直到時鐘超過原本的時間（[哪些時間算遊玩時間](https://guard.boreale.dev/zh-hant/docs/features.md#哪些時間算遊玩時間)）。
- **另一個系統。** emuMMC 和 sysMMC 各有各的家長監護：請在兩邊都設定，或隱藏 hekate 的開機選單（[相容性](https://guard.boreale.dev/zh-hant/docs/compatibility.md#emummc-和-sysmmc)）。

### 今天又可以使用整個上限了

變更時鐘（網路時鐘或主機時鐘）會讓今天的遊玩時間重新計算。請在孩子玩之前設定時鐘，而不是之後。

### PlayGuard 以唯讀方式開啟

主機執行的韌體比測試過的最新韌體還新：PlayGuard 會檢查是否有更新的版本支援它，並建議更新（[韌體比較新](https://guard.boreale.dev/zh-hant/docs/compatibility.md#韌體比較新)）。標題右側劃掉的鉛筆表示應用程式為唯讀；點一下它會開啟韌體畫面。

### PlayGuard 一直要求輸入PIN碼，或從不要求

*安全 › 用PIN碼保護PlayGuard*：*變更前*（預設）會在第一次變更前詢問一次，PIN碼在 PlayGuard 關閉前都有效。*5分鐘後再次詢問PIN碼*會在 5 分鐘後再次詢問。*顯示PIN碼*每次都會要求輸入。

### 遊戲無法啟動，或在 HOME 選單上顯示「!」

*主機 › 已安裝的遊戲*會說明每款遊戲的問題和該怎麼做；存檔資料一律保留（[已安裝的遊戲](https://guard.boreale.dev/zh-hant/docs/features.md#已安裝的遊戲)）。

### 受保護的轉發器顯示錯誤 2347-0100

它的關卡（`config/playguard/gate-….nro`）已不再是製作轉發器時的那個檔案：它在 SD 卡上被變更或取代了，所以轉發器不會啟動它。請從 PlayGuard 自己的轉發器開啟 PlayGuard：它在啟動時會把關卡寫回去；*主機 › 轉發器 › 全部重新安裝*會用它重新製作所有轉發器。

### 受保護的轉發器一開啟就關閉（「發生錯誤」）

在出現任何 PlayGuard 畫面之前，沒有錯誤代碼（Atmosphère 在 `atmosphere/crash_reports/` 中的報告會指出 `forwarder` 模組，結果為 `2000-0000`）：它是由某個 PlayGuard 製作的，而那個 PlayGuard 的關卡在建置時缺少資源，被轉發器的載入程式拒絕了。請更新 PlayGuard，然後重新製作它：鈴鐺和*主機 › 轉發器*會為每個用較舊載入程式製作的轉發器提供這個操作。

### 受保護的轉發器輸入PIN碼後停在關卡畫面上

PIN碼已被接受，附有 Homebrew 圖示的畫面卻一直停著，之後什麼也沒有發生：它的關卡用單一緩衝區繪製了那個畫面，然後一直等待繪製下一個畫面。請更新 PlayGuard，然後重新製作它：鈴鐺和*主機 › 轉發器*會為每個用較舊關卡製作的轉發器提供這個操作。

### 轉發器顯示「無法啟動軟體」

主機拒絕啟動它：仍有一項簽章檢查在作用。請依下列順序檢查：

- **sys-patch 旁邊還有 sigpatch 檔案。** sys-patch 執行時，`atmosphere/kip_patches/fs_patches`、`loader_patches` 或 `atmosphere/exefs_patches/es_patches` 中還有 `.ips` 檔案：兩個工具在修補相同的檢查，這是 GBAtemp 上 sys-patch 和 sigpatch 討論串中最常提到的原因。*主機 › 遊戲修補*會對此發出提醒，在那裡按 Ⓐ 可以把它們移到一旁（移到 `config/playguard/sigpatches-aside/`，絕不刪除；hekate 的 `bootloader/patches.ini` 保持不動）。接著重新啟動主機。
- **sys-patch 沒有套用某個特徵碼。** 轉發器需要它的 fs 和 loader 修補，也就是它針對這個韌體的所有特徵碼（`noncasigchk_17.0.0+`、`nocntchk_19.0.0+`、`noacidsigchk_10.0.0+`），而不只是每個模組一個。*關於 › 說明與診斷 › 匯出診斷報告*會在它的 `game patches` 一行列出 sys-patch 的版本和每個沒有套用的特徵碼；`sd:/config/sys-patch/log.ini` 中也有相同的內容。請確認 `config/sys-patch/config.ini` 會修補這個系統（emuMMC 上為 `patch_emummc=1`），而且沒有關閉其中任何一項；sys-patch 的維護者本人表示，23.0.x 不需要比 1.6.2.3 更新的 sys-patch。
- **修補變更後沒有重新啟動。** sys-patch 會在開機時修補。
- **由較早版本的 PlayGuard 製作的轉發器。** 鈴鐺和*主機 › 轉發器*會建議重新製作那些用較舊載入程式建置的轉發器。

### 鈴鐺或某個分頁顯示琥珀色標記

有事情需要你處理：Ⓨ 開啟清單，在項目上按 Ⓐ 會直接修正，或開啟可以修正它的地方（[通知](https://guard.boreale.dev/zh-hant/docs/features.md#通知在任何分頁都能看到需要你處理的事)）。

## 回報錯誤

發生錯誤時會顯示系統代碼（例如 `0x0001088E`），以及關於它的已知資訊：對於意義已有文件記載的代碼，會說明該怎麼做；其他情況，一份報告會很有幫助。

1. *關於 › 說明與診斷 › 匯出診斷報告*會在 `sd:/config/playguard/logs/reports/` 儲存一個文字檔：韌體、Atmosphère 版本、啟動花了多久、較慢的畫面花了多久（變更紀錄、*所有遊戲*、已安裝遊戲的檢查、會自動重新整理的分頁）、時鐘、儲存空間、序號遮蔽與遊戲修補的狀態、Atmosphère 的 DNS 重新導向如何處理任天堂的家長監護和時間伺服器（從 SD 卡上它的 hosts 檔案讀取，而不是網路測試，並附上 Atmosphère 自己的 `atmosphere/logs/dns_mitm_startup.log` 的結尾）、每一次家長監護查詢的原始結果，以及記錄：上次執行如何結束、剩餘的記憶體和 SD 卡空間、最新的當機檔案，以及最後 80 行記錄。**它絕不包含PIN碼或序號。**
2. [開一個 issue](https://github.com/JigSawFr/PlayGuard/issues/new)（英文），並附上這個檔案。

### 線上傳送報告

在主機連網時，*關於 › 說明與診斷 › 傳送報告…*（開發者模式下，在診斷報告上按 Ⓧ）會把報告傳送到你 GitHub 帳戶中的一個秘密 gist。傳送前，它會清楚說明要傳送哪些內容。先前儲存在 `logs/reports/` 中的報告也可以用同樣的方式傳送。

- **傳送的內容：** 報告和每個檔案各自成為一個檔案：
  - 最近的當機報告：PlayGuard 在 `logs/crashes/` 中的最後 3 份，以及 Atmosphère 在 `sd:/atmosphere/crash_reports/` 中過去一週內某個 homebrew 的最後 2 份（其中可能包含其他 homebrew 的當機：傳送前顯示的清單會標明是哪些）；
  - 這次及上一次執行的記錄（`logs/sessions/`；記錄太長時：開頭部分和最後 64 KiB）；
  - 除錯檔案：遊玩時間限制區塊的參考、*記錄遊玩時間限制*開啟時遊玩時間記錄的最後部分、變更紀錄的最後 20 筆（不含遊戲、帳號或設定檔的名稱，只保留日期），以及 PlayGuard 的設定。
- **登入：** 未登入時，PlayGuard 會先提議登入；登入後，正下方的 *GitHub 帳戶*可以登出；GitHub 拒絕建立 gist 時，PlayGuard 會提議重新登入。
- **之後：** 它會顯示兩個 QR 碼，連結顯示在第一個下方，它的 ID 每四個字元一組，方便念出或輸入：一個是報告，給已經在協助你的人；另一個是錯誤回報表單，已預先填好連結、你的版本、PlayGuard 的啟動方式（在遊戲之上、從它在 HOME 選單上的圖示，或從相簿；請補上選單）以及系統（sysMMC 或 emuMMC），掃描即可回報錯誤。連結也會保留在通知中，每個連結都會以網際網路捷徑（`.url`）的形式保存在 `logs/uploads/`，電腦可以用瀏覽器開啟。

> [!WARNING]
> 任何拿到連結的人都能閱讀報告，直到你在 GitHub 上刪除該 gist 為止；用它開立的錯誤回報是公開的：確認畫面會說明這一點。

### PlayGuard 在 SD 卡上保存的內容

全部都在 `sd:/config/playguard/logs/`，是電腦可以開啟的純文字：

- `sessions/session_<date>.txt`——**每次執行一個檔案**：PlayGuard 記錄的所有內容（以前只能透過 nxlink 傳到電腦），每一行都有時間和等級（`E` 錯誤、`W` 警告、`I` 資訊），最後一行說明這次執行如何結束：`=== end: clean exit ===`（正常結束），或 `=== end: crash, see logs/crashes/… ===`（當機）。檔案達到 1 MiB 後就不再增加。
- `crashes/crash_<date>.txt`——**每次當機一個檔案**，第一行說明發生了什麼：
  - **CPU 例外**（錯誤的指標、未定義的指令、堆疊溢位）：錯誤的類型和存取的位址、回溯追蹤（backtrace）和暫存器。位址是 `playguard.nro` 中的偏移量（`playguard+0x1a2b3c`）：該建置的連結器對照表（其 CI 執行產生的 `-linker-map` 成品）可以查出對應的函式。之後 PlayGuard 會和以前一樣結束：顯示主機的錯誤畫面，並由 Atmosphère 在 `sd:/atmosphere/crash_reports/` 寫入它自己的報告；
  - **未捕捉的例外**：它的類型和訊息，以及回溯追蹤；
  - **未正常結束的執行**：在下次啟動時發現，也就是上次執行的工作階段檔案沒有結束行時（PlayGuard 無法捕捉的當機、在當住時從 HOME 選單關閉，或主機被關機），附上那次執行的最後 60 行。

  PlayGuard 執行期間捕捉到的當機，其檔案結尾會附上當機前記錄的最後 80 行。
- `reports/`、`uploads/`、`play_timer/`——已儲存的報告、線上傳送的報告的連結、遊玩時間記錄。

*關於 › 說明與診斷*可以設定要保留多少報告、當機檔案、工作階段記錄和連結（每個資料夾分開設定；最新的一份一定會保留）。

## 開發者模式（調查新的韌體）

在*關於 › 版本*上按 Ⓨ 七次；開發者工具會出現在*關於 › 說明與診斷*的最後。它會加入：

- 一個**唯讀**開關——開啟時，應用程式無法變更任何設定：這是調查新韌體的安全方式（韌體畫面會直接提供這個選項）；
- 在畫面上顯示診斷報告（Ⓨ 儲存，Ⓧ 線上傳送），以及從遊玩時間限制分頁匯出報告的捷徑；
- **主機自我檢測**：在手動逐項完成[主機檢查清單](https://github.com/JigSawFr/PlayGuard/blob/main/docs/hardware-test.md)（英文）之前，PlayGuard 自己在這台主機上檢查的項目——PIN碼、簽章修補、資料夾、PlayGuard 建立的每個轉發器（是否在 HOME 選單上、是否受保護、是否已確認能透過關卡正常運作）、SD 卡上的關卡、Atmosphère 讀到的 Homebrew 選單鎖定、返回途徑、復原 sysmodule。它不會變更任何設定，並把結果以 Markdown 寫入 `config/playguard/self-test.md`，可以貼到 pull request 中；
- 直接在原處**安裝其他建置**，在修正正式發布前先行測試（[見下文](#安裝其他建置)）；
- **比對遊玩時間限制資料區塊**（僅在手機應用程式已連動且能夠同步時——以 hosts 檔案封鎖任天堂時則不行；也會出現在*安全*中），用來解讀 PlayGuard 還沒有顯示的設定：把原始區塊儲存為參考，在手機應用程式中變更一項設定，再回來——PlayGuard 會列出有變動的數值（可依需要儲存到 `logs/reports/`）。透過手機應用程式設定的每天不同的就寢時間，可以用這個方法確認。請把該檔案附加到 issue 上，或隨報告一起傳送（*傳送報告…*）。
- **記錄遊玩時間限制**：PlayGuard 開啟期間，每 30 秒把遊玩時間限制回報的內容（剩餘時間、已遊玩時間、原始設定區塊……）寫成一行，存到 `logs/play_timer/log.csv`，這是可以用試算表開啟的檔案；PlayGuard 每次變更後也會立即寫入一行，說明是哪一項變更（最後一欄 `event`），當時鐘移動的幅度超過實際經過的時間時，也會加上註記。讓它開著跨過午夜，或一直開到時間用完，它就能顯示單一報告無法呈現的內容：已遊玩時間何時歸零、主機在快結束時顯示什麼。這個開關會被記住；它只在開發者模式下記錄。目前已知的內容請見 [parental-controls.md](https://guard.boreale.dev/zh-hant/docs/parental-controls.md)（英文）。
- **清除快取**和**刪除記錄檔**，各自在確認畫面說明檔案數量和佔用空間後執行：快取（`cache/` 以及每個系統的 `nand/<system>/cache/`：遊戲名稱和圖示、活動紀錄的最近數據、建置清單）在需要時會從主機重新讀取；記錄檔包括當機檔案、工作階段記錄（但不含這次執行、仍在寫入中的記錄）、已儲存的報告和遊玩時間記錄，而 `uploads/`（線上傳送的報告的刪除連結）和區塊參考會保留。設定、紀錄、備份、設定檔和匯出檔案絕不會被動到。
- **重新執行移轉**：從先前配置的移轉（`.nro` 旁邊的資料夾、記錄檔分成子資料夾之前的位置、所有系統共用的內容）各佔一行，可以勾選或取消勾選（一開始全部勾選；A 切換一項），然後是*執行所選的 N 項*，以及一個列出各項及其移動內容的確認畫面。無論 `migrations.json` 記錄了什麼，它們都會立即執行（否則每項只會在需要它的建置首次啟動時執行一次；記錄的等級絕不會降低）；已在原位的檔案絕不會被取代。對話框會說明移動了多少項目；每個步驟都會寫入工作階段記錄。
- **影格統計**：每秒在 `logs/frame_stats.txt` 中寫入一行，包括繪製畫面所花的時間和延遲的影格，用來在主機上比較不同畫面的表現。**背景光暈**可以關閉畫面後方的柔和光線（此時該行的模式會以 `-noglow` 結尾），以衡量它的成本。

### 安裝其他建置

*安裝其他建置*會用一個建置取代 PlayGuard 自己的 `.nro`，在修正正式發布前先行測試。

**它列出的建置**，每一類各在一個分頁中（Ⓛ / Ⓡ 顯示在分頁兩側，用來切換分頁；畫面會開在已安裝建置所屬的分頁，每個分頁的名稱後面都有一個閃光標記和比已安裝建置更新的建置數量）：

- 最近 20 個版本之一（包括預先發布，會加上標籤）；
- `main` 最近 20 個提交之一；
- 從本儲存庫的分支開啟的拉取請求的最新建置（絕不接受來自 fork 的：它的程式碼還沒有經過審查）。在拉取請求分頁顯示時，按 A 可以反轉排序（最新建置在前，或依編號）：A 的操作提示會說明是哪一種。

**每個建置**都會顯示標題（提交或拉取請求的主旨；提交的完整訊息就是它的說明），下方是標籤：變更的類型（*新功能*、*修正*、*文件*……）和範圍、*不相容*、提交所屬的拉取請求、檢查的結果（*CI 通過*、*CI 失敗*、*CI 進行中*）、預先發布、已安裝的建置附勾號、較新的建置附閃光標記；右側是建置的時間（以分鐘、小時，然後以天計）和提交。選擇一個建置會先開啟它的頁面：標籤（類型、檢查結果、勾號或閃光標記）、一張資訊卡（建置時間、大小、提交、校驗碼、GitHub 何時刪除它）、**安裝**、**在 GitHub 上查看**（它的頁面以 QR 碼顯示，供手機掃描），檢查仍在進行時會顯示一則警告，接著是版本的說明或拉取請求的描述，依照 GitHub 的 Markdown 排版（標題、清單、核取方塊、程式碼、引言和提示框、表格）。

**可以安心閱讀：** 來自 GitHub 的所有內容都以純文字顯示：不會開啟任何連結，不會執行任何 HTML 或腳本，並會移除可能用來偽裝標題的隱形字元（由右至左覆寫、零寬度字元、控制字元、無效的 UTF-8）。

**登入。** 正式版本不需要任何條件；其他建置是建置工作流程的成品，GitHub 只提供給已登入的使用者。**GitHub 帳戶**會以一組代碼和一個供手機掃描的 QR 碼登入。只要求讀取建置工作流程檔案（Actions）以及建立 gist 的權限，後者用於*傳送報告…*；除此之外，權杖只能讀取公開內容。權杖保存在 `github_token`，絕不會隨報告傳送，*GitHub 帳戶*也可以登出。登入後，Ⓨ（*搜尋*）可以輸入拉取請求的編號（開啟或已關閉的）或提交（7 到 40 位十六進位數字），找出它的建置，僅限本儲存庫的分支。

**安裝：** PlayGuard 會下載建置、檢查它（大小、GitHub 記錄的 SHA-256、NRO 標頭），用它取代自己的 `.nro`，然後以新建置重新啟動（只要設有PIN碼，就會先要求輸入）。它的視窗會說明目前在哪一步、下載的大小和速度，以及它取代的是哪個建置；開始放置建置後，「取消」就會消失。

- 清單會保留 10 分鐘並立即顯示，同時標明它是多久前取得的（Ⓧ 重新取得，建置的檢查仍在進行時，畫面也會每 3 分鐘重新取得）；取得期間，標題列右側會有一條進度列顯示進度。安裝會做什麼，則在畫面底部說明。
- 中斷的下載（網路斷線）會在下次安裝同一個建置時從中斷處繼續。
- 成品會在 90 天後過期。

**回到上一個建置。** 被取代的建置會保留下來（`playguard.nro.previous`）：同一個清單中的**回到上一個建置**可以在輸入PIN碼後再把它們換回來；它會以版本、拉取請求和提交標明那個建置。如果從這裡安裝的建置（或透過*更新方式*的*在 PlayGuard 內*更新的版本）在第一個畫面出現前就當機，PlayGuard 下次啟動時，會在載入任何東西之前，以一個簡單的文字畫面提議回到上一個建置（A 回到上一個，B 仍然啟動它）。設定了PIN碼時，回到上一個建置會在主機本身的PIN碼畫面上要求輸入PIN碼（而不是 PlayGuard 的鎖定畫面，當機的可能正是它）；不輸入則啟動已安裝的建置。同一個清單隨時都能回到任何一個正式版本。

**正在執行的建置：** 在開發者模式下，*關於 › 版本*會顯示提交。每個畫面的標題列都會在標題旁顯示目前執行的版本：正式版本顯示在灰色標籤中（`1.2.0`），其他建置則顯示在琥珀色標籤中並接著顯示提交，讓測試建置絕不會被誤認為正式版本。
