<!-- translated from docs/troubleshooting.md, sha256 dbe5760f150d -->
# Решение проблем

Как вернуть доступ к заблокированной консоли, частые проблемы, как сообщить об ошибке и включить режим разработчика.

## Нет доступа?

PlayGuard видит только родительский контроль той системы, на которой работает: **у emuMMC и у sysMMC он свой** (PIN-код, удалённый в одной, остаётся в другой). Запустите PlayGuard в каждой системе, которую нужно исправить.

### Консоль с рук

Вы знаете PIN-код, но мобильное приложение прежнего владельца всё ещё привязано (отвязать не получается, или сброс к заводским настройкам требует его учётную запись).

*Защита › Отвязать мобильное приложение*, затем, если родительский контроль вам совсем не нужен, *Удалить родительский контроль*. Оба действия работают без интернета, в emuMMC так же, как в sysMMC.

### Забыли PIN-код

*Показать PIN-код* сам запрашивает PIN-код, поэтому здесь не поможет. Если установлен модуль восстановления (см. ниже), положите файл `RESCUE` и перезапустите консоль: экран восстановления задаст новый PIN-код (старый он никогда не показывает). Без модуля *Удалить родительский контроль* позволяет начать заново (сначала сохраняется резервная копия настроек; PIN-кода в ней никогда нет): если включено *Защитить PlayGuard PIN-кодом* (по умолчанию — *Перед изменением*), сначала вставьте SD-карту в компьютер и задайте `"pin_lock"` значение `"off"` в `sd:/config/playguard/config.json`.

### Таймер игры блокирует всё (лимит 0 минут), а PIN-код забыт

Тогда не запускается и сам PlayGuard. Установите необязательный модуль восстановления **заранее** (*Консоль › Дополнительные модули* или вручную `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` из этого выпуска (или нажмите *Обновить* в уведомлении *Модуль восстановления устарел* под колокольчиком), затем перезапустите консоль. Более старый модуль оставляет отчёт, который PlayGuard не может проверить: экран восстановления тогда ничего не предлагает, сообщает, что модуль старее, и повторный `RESCUE` даёт то же самое, пока модуль не обновлён.

### Меню homebrew заблокировано

*Консоль › Форвардеры › Заблокировать меню homebrew* не даёт альбому и игре, запущенной с R, открывать меню homebrew. Если и форвардер PlayGuard, и защищённое меню пропали (удалены в системных настройках или находятся в другой системе: блокировка хранится на SD-карте, её читают и sysMMC, и emuMMC):

- **С компьютера:** удалите `atmosphere/config/override_config.ini` на SD-карте (или верните `config/playguard/override_config.ini.backup` — файл в исходном виде), затем перезапустите консоль.
- **С установленным модулем восстановления** (необязательно): положите на SD-карту пустой файл `config/playguard/RESCUE` и перезапустите консоль; модуль снимет блокировку при загрузке, и PlayGuard сообщит об этом при следующем запуске. Обновление Atmosphère после блокировки снимает её так же.

### Консоль без модификаций

PlayGuard здесь не поможет: ему нужна Atmosphère. Официальный путь — процедура мастер-ключа через поддержку Nintendo.

## Частые проблемы

### Оставшееся время не уменьшается

*Сегодня* сообщает *Консоль сейчас не считает время игры*, когда оно не менялось около 90 с. Вероятные причины:

- **Сетевые часы ни разу не выставлялись.** *Консоль › Сетевые часы › Измерить расхождение*, затем выставьте их ([сетевые часы](https://guard.boreale.dev/ru/docs/features.md#сетевые-часы)).
- **Часы перевели назад.** После перевода назад счёт останавливается, пока часы не пройдут прежнее время; делать ничего не нужно.
- **Лимит только что записан.** Запустите игру на минуту, затем проверьте снова.
- **Родительский контроль временно разблокирован.** Игровое время тогда может не считаться: *Сегодня › Включить снова* (или нажатие на плашку в заголовке).

### Мои лимиты изменились сами

- **Мобильное приложение всё ещё привязано.** Его следующая синхронизация перезаписывает то, что задал PlayGuard: *Защита › Отвязать мобильное приложение*.
- **Другой инструмент или профиль.** *Сегодня* показывает янтарную карточку, если лимиты отличаются от тех, что PlayGuard видел в последний раз, а *История › Изменения через PlayGuard* перечисляет каждое изменение, замеченное вне PlayGuard. Ⓐ на нём возвращает прежнее значение.
- **Запланированный профиль** применился или вернул прежние лимиты по окончании своего периода (*Таймер игры › Профили › Запланированный профиль*).

### Ребёнок играл дольше лимита

- **Консоль только предупреждает.** *Таймер игры › Когда время вышло*: выберите *Приостановить программу*.
- **Родительский контроль остался разблокированным.** Пока это так, лимит на сегодня приостановлен: об этом говорит плашка в заголовке на каждой вкладке, а нажатие на неё ведёт к *Сегодня › Включить снова*. Перезапуск консоли тоже его блокирует.
- **Часы перевели назад.** Счёт останавливается, пока часы не пройдут прежнее время ([что считается](https://guard.boreale.dev/ru/docs/features.md#что-считается-игровым-временем)).
- **Другая система.** У emuMMC и sysMMC свой родительский контроль: настройте его в обеих или скройте загрузочное меню hekate ([совместимость](https://guard.boreale.dev/ru/docs/compatibility.md#emummc-и-sysmmc)).

### Сегодня снова доступен весь лимит

Изменение часов (сетевых часов или часов консоли) обнуляет сегодняшнее игровое время. Выставляйте часы до того, как ребёнок начнёт играть, а не после.

### PlayGuard открывается только для чтения

На консоли прошивка новее самой новой из проверенных: PlayGuard проверяет, поддерживает ли её более новый выпуск, и предлагает обновиться ([прошивка новее](https://guard.boreale.dev/ru/docs/compatibility.md#прошивка-новее)). Перечёркнутый карандаш справа от названия означает, что приложение работает только для чтения; нажатие на него открывает экран прошивки.

### PlayGuard всё время спрашивает PIN-код или никогда не спрашивает

*Защита › Защитить PlayGuard PIN-кодом*: *Перед изменением* (по умолчанию) спрашивает один раз, перед первым изменением, и PIN-код действует, пока PlayGuard не закроется. *Запрашивать PIN-код снова через 5 минут* спрашивает снова по истечении этого времени. *Показать PIN-код* спрашивает всегда.

### Игра не запускается или показывает «!» в меню HOME

*Консоль › Игры* говорит, что не так с каждой игрой и что делать; сохранения всегда остаются ([установленные игры](https://guard.boreale.dev/ru/docs/features.md#установленные-игры)).

### Защищённый форвардер показывает ошибку 2347-0100

Его ворота (`config/playguard/gate-….nro`) — уже не тот файл, с которым форвардер был создан: их изменили или заменили на SD-карте, поэтому форвардер их не запускает. Откройте PlayGuard с его собственного форвардера: при запуске он записывает ворота заново; *Консоль › Форвардеры › Переустановить все* пересоздаёт с ними все форвардеры.

### Защищённый форвардер сразу закрывается («Произошла ошибка»)

До любого экрана PlayGuard, без кода ошибки (отчёт Atmosphère в `atmosphere/crash_reports/` называет модуль `forwarder`, результат `2000-0000`): он создан версией PlayGuard, ворота которой были собраны без своих ресурсов, и загрузчик форвардера их отверг. Обновите PlayGuard, затем создайте форвардер заново: колокольчик и *Консоль › Форвардеры* предлагают это для каждого форвардера, созданного с более старым загрузчиком.

### Защищённый форвардер остаётся на экране ворот после PIN-кода

PIN-код принят, экран со значком homebrew-программы остаётся, и больше ничего не происходит: его ворота рисовали этот экран с одним буфером и бесконечно ждали, чтобы нарисовать следующий. Обновите PlayGuard, затем создайте форвардер заново: колокольчик и *Консоль › Форвардеры* предлагают это для каждого форвардера, созданного с более старыми воротами.

### Форвардер показывает «Не удалось запустить программу»

Консоль отказалась его запускать: проверка подписи всё ещё действует. В порядке проверки:

- **Файлы sigpatch рядом с sys-patch.** Файлы `.ips` в `atmosphere/kip_patches/fs_patches`, `loader_patches` или `atmosphere/exefs_patches/es_patches`, пока работает sys-patch: два инструмента патчат одни и те же проверки — причина, которую чаще всего называют темы о sys-patch и sigpatch на GBAtemp. *Консоль › Патчи игр* предупреждает об этом, и Ⓐ там убирает их в сторону (перемещает в `config/playguard/sigpatches-aside/`, никогда не удаляет; `bootloader/patches.ini` hekate остаётся). Перезапустите консоль.
- **Шаблон, который 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` патчит эту систему (`patch_emummc=1` в emuMMC) и не отключает ни один из них; сам сопровождающий sys-patch говорит, что для 23.0.x не нужен sys-patch новее 1.6.2.3.
- **Не было перезапуска после изменения патчей.** sys-patch патчит при загрузке.
- **Форвардер, созданный более старой версией PlayGuard.** Колокольчик и *Консоль › Форвардеры* предлагают заново создать те, что собраны с более старым загрузчиком.

### Колокольчик или вкладка показывает янтарный значок

Что-то требует вашего внимания: Ⓨ открывает список, а Ⓐ на записи выполняет исправление или открывает место, где оно делается ([уведомления](https://guard.boreale.dev/ru/docs/features.md#уведомления--что-требует-вашего-внимания-с-любой-вкладки)).

## Как сообщить об ошибке

Ошибка показывает системный код (например, `0x0001088E`) и то, что о нём известно: что делать — для кодов с известным значением, в остальных случаях поможет отчёт.

1. *О программе › Помощь и диагностика › Экспорт отчёта диагностики* сохраняет текстовый файл в `sd:/config/playguard/logs/reports/`: прошивка, версия Atmosphère, сколько длился запуск и сколько — медленные экраны (история изменений, *Все игры*, проверка установленных игр, вкладки, которые обновляются сами), часы, хранилище, состояние скрытия серийного номера и патчей игр, что DNS-перенаправление Atmosphère делает с серверами родительского контроля и времени Nintendo (по его файлу hosts на SD-карте, а не сетевой проверкой, с концом собственного `atmosphere/logs/dns_mitm_startup.log` Atmosphère), необработанный результат каждого запроса к родительскому контролю и журналы: как закончился последний запуск, оставшиеся память и место на SD-карте, последние файлы сбоев и последние 80 строк журнала. **В нём никогда нет PIN-кода и серийного номера.**
2. [Откройте issue](https://github.com/JigSawFr/PlayGuard/issues/new) и приложите его.

### Отправка отчёта в интернет

Если консоль в сети, *О программе › Помощь и диагностика › Отправить отчёт…* (Ⓧ на отчёте диагностики в режиме разработчика) отправляет его в секретный gist в вашем аккаунте GitHub, предварительно точно сказав, что будет отправлено. Отчёт, сохранённый ранее в `logs/reports/`, можно отправить так же.

- **Что отправляется:** отчёт и каждый файл — отдельными файлами:
  - последние отчёты о сбоях: последние 3 сбоя PlayGuard из `logs/crashes/` и последние 2 отчёта Atmosphère о сбоях homebrew за прошедшую неделю из `sd:/atmosphere/crash_reports/` (среди них может оказаться сбой другого homebrew: список, показанный перед отправкой, говорит, какой);
  - журналы этого и предыдущего запуска (`logs/sessions/`; от длинного — начало и последние 64 КиБ);
  - отладочные файлы: эталон блока таймера игры, конец записи таймера игры, пока включено *Записывать таймер игры*, последние 20 изменений из истории (без названий игр, пользователей или профилей и только с датой) и настройки PlayGuard.
- **Вход:** если вход не выполнен, PlayGuard сначала предложит войти; *Аккаунт GitHub*, чуть ниже после входа, позволяет выйти; если GitHub отклоняет gist, PlayGuard предлагает войти снова.
- **После отправки:** он показывает два QR-кода, со ссылкой под первым и её id группами по четыре символа, чтобы продиктовать или набрать: отчёт — для того, кто уже вам помогает, и форму сообщения об ошибке, где уже заполнены ссылка, ваши версии, как был запущен PlayGuard (поверх игры, со своего значка в меню HOME или из альбома; допишите меню) и система (sysMMC или emuMMC), — отсканируйте её, чтобы сообщить об ошибке. Ссылка также остаётся в уведомлениях, и каждая хранится в `logs/uploads/` как интернет-ярлык (`.url`), который компьютер открывает в браузере.

> [!WARNING]
> Любой, у кого есть ссылка, может прочитать отчёт, пока вы не удалите gist на GitHub, а сообщение об ошибке, открытое с ней, публично: подтверждение об этом предупреждает.

### Что PlayGuard хранит на SD-карте

Всё лежит в `sd:/config/playguard/logs/`, в виде обычного текста, который открывается на компьютере:

- `sessions/session_<date>.txt` — **по файлу на каждый запуск**: всё, что PlayGuard записал в журнал (раньше это доходило до ПК только через nxlink), каждая строка со временем и уровнем (`E` — ошибка, `W` — предупреждение, `I` — информация), и последняя строка о том, как закончился запуск: `=== end: clean exit ===` или `=== end: crash, see logs/crashes/… ===`. Файл перестаёт расти на 1 МиБ.
- `crashes/crash_<date>.txt` — **по файлу на каждый сбой**, первая строка говорит, что произошло:
  - **исключение процессора** (неверный указатель, неопределённая инструкция, переполнение стека): тип сбоя и адрес, к которому было обращение, трассировка стека и регистры. Адреса — это смещения в `playguard.nro` (`playguard+0x1a2b3c`): карта компоновщика этой сборки (артефакт `-linker-map` её запуска CI) даёт функцию. Затем PlayGuard завершается, как и раньше: экран ошибки консоли и собственный отчёт Atmosphère в `sd:/atmosphere/crash_reports/`;
  - **неперехваченное исключение**: его тип и сообщение, и трассировка стека;
  - **незавершённый запуск**: обнаруживается при следующем запуске, когда в файле сеанса прошлого запуска нет последней строки (сбой, который PlayGuard не смог перехватить, закрытие из меню HOME во время зависания или выключение консоли), с последними 60 строками того запуска.

  Файлы сбоев, перехваченных во время работы PlayGuard, заканчиваются последними 80 строками журнала перед сбоем.
- `reports/`, `uploads/`, `play_timer/` — сохранённые отчёты, ссылки на отчёты, отправленные в интернет, запись таймера игры.

*О программе › Помощь и диагностика* задаёт, сколько отчётов, файлов сбоев, журналов сеансов и ссылок хранить (для каждой папки отдельно; самый новый остаётся всегда).

## Режим разработчика (изучение новой прошивки)

Нажмите Ⓨ семь раз на *О программе › Версия*; инструменты разработчика появятся в конце *О программе › Помощь и диагностика*. Режим добавляет:

- переключатель **только для чтения** — когда он включён, приложение ничего не может изменить: безопасный способ изучать новую прошивку (экран прошивки предлагает его сразу);
- отчёт диагностики на экране (Ⓨ сохраняет его, Ⓧ отправляет в интернет) и ярлык для его экспорта на вкладке «Таймер игры»;
- **Самопроверка консоли**: то, что PlayGuard сам проверяет на этой консоли, прежде чем [контрольный список для консоли](https://github.com/JigSawFr/PlayGuard/blob/main/docs/hardware-test.md) (на английском) будет пройден вручную, — PIN-код, патчи подписей, папка данных, каждый форвардер, созданный PlayGuard (в меню HOME, защищён, замечен в работе через свои ворота), ворота на SD-карте, что Atmosphère читает о блокировке меню homebrew, пути назад, модуль восстановления. Она ничего не меняет и записывает результат в формате Markdown в `config/playguard/self-test.md`, чтобы вставить его в pull request;
- **Установить другую сборку** на место текущей, чтобы проверить исправление до выпуска ([ниже](#установка-другой-сборки));
- **Сравнить блок таймера игры** (только пока мобильное приложение привязано и может синхронизироваться — не с файлом hosts, который блокирует Nintendo; также на вкладке *Защита*), чтобы расшифровать настройки, которые PlayGuard пока не показывает: сохраните необработанный блок как эталон, измените одну настройку в мобильном приложении, вернитесь — PlayGuard перечислит изменившиеся значения (по запросу сохраняются в `logs/reports/`). Так можно было бы подтвердить разное время «Пора спать» для разных дней, заданное в мобильном приложении. Приложите этот файл к issue или отправьте его с отчётом (*Отправить отчёт…*).
- **Записывать таймер игры**: каждые 30 с, пока PlayGuard открыт, одна строка с тем, что сообщает таймер игры (оставшееся время, затраченное время, необработанный блок настроек…), в `logs/play_timer/log.csv` — файл, готовый для электронной таблицы, плюс строка сразу после каждого изменения, сделанного PlayGuard, с указанием какого (последний столбец, `event`), и пометка, когда часы сдвинулись больше, чем прошло времени. Если оставить его открытым через полночь или до конца времени, он покажет то, чего не покажет один отчёт: когда сбрасывается затраченное время и что консоль говорит ближе к концу. Переключатель запоминается; запись идёт только в режиме разработчика. То, что известно на сегодня, описано в [parental-controls.md](https://guard.boreale.dev/ru/docs/parental-controls.md) (на английском).
- **Очистить кэш** и **Удалить файлы журналов**, каждое после подтверждения с числом файлов и занимаемым местом: кэш (`cache/` и `nand/<system>/cache/` каждой системы: названия и значки игр, последние данные «Активности», список сборок) при необходимости читается с консоли заново; файлы журналов — это файлы сбоев, журналы сеансов (кроме текущего, который ещё пишется), сохранённые отчёты и запись таймера игры, а `uploads/` (ссылки для удаления отчётов, отправленных в интернет) и эталон блока остаются. Настройки, история, резервные копии, профили и экспорт никогда не затрагиваются.
- **Повторить миграции**: переносы из прежних раскладок — папка данных рядом с `.nro`, журналы до появления их подпапок, то, что было общим для всех систем, — каждый на своей строке, которую можно отметить или снять (сначала отмечены все; A переключает одну), затем *Выполнить выбранные (N)* и подтверждение со списком того, что переносит каждая. Они выполняются сразу, что бы ни было записано в `migrations.json` (иначе каждая выполняется один раз, при первом запуске сборки, которой она нужна; записанный уровень никогда не понижается); файл, который уже на месте, никогда не заменяется. Окно сообщает, сколько элементов перенесено; каждый шаг записан в журнал сеанса.
- **Статистика кадров**: одна строка в секунду в `logs/frame_stats.txt` — время, за которое отрисован экран, и опоздавшие кадры, чтобы сравнивать экраны между собой на консоли. **Свечение фона** выключает мягкий свет за экранами (режим в строке тогда заканчивается на `-noglow`), чтобы измерить, чего оно стоит.

### Установка другой сборки

*Установить другую сборку* ставит сборку на место собственного `.nro` PlayGuard, чтобы проверить исправление до выпуска.

**Что в списке**, каждый вид — на своей вкладке (Ⓛ / Ⓡ, показанные по обе стороны вкладок, переключают их; экран открывается на вкладке установленной сборки, и у каждой вкладки после названия — искорка и число сборок новее установленной):

- один из последних 20 выпусков (включая предварительные, с пометкой);
- один из последних 20 коммитов `main`;
- новейшая сборка открытого pull request из ветки этого репозитория (никогда из форка: его код ещё не проверен). A на вкладке pull request, когда она показана, меняет порядок сортировки (сначала новейшая сборка или по номеру): подсказка A говорит, какой.

**У каждой сборки** есть заголовок (тема коммита или pull request; полное сообщение коммита — его описание) и метки под ним: вид изменения (*Новое*, *Исправление*, *Документация*…) и его область, *Несовместимо*, pull request, из которого пришёл коммит, чем закончились проверки (*CI OK*, *CI не пройдена*, *CI идёт*), предварительный выпуск, галочка, если это установленная сборка, или искорка, если она новее; справа — возраст сборки (в минутах, часах, затем днях) и её коммит. Сборка сначала открывает свою страницу: метки (вид, проверки, галочка или искорка), карточка с фактами (дата сборки, размер, коммит, контрольная сумма, когда GitHub её удалит), **Установить**, **Открыть на GitHub** (её страница в виде QR-кода для телефона), предупреждение, если её проверки ещё идут, затем заметки к выпуску или описание pull request, отрисованные из Markdown GitHub (заголовки, списки, флажки задач, код, цитаты и предупреждения, таблицы).

**Безопасно для чтения:** всё, что приходит с GitHub, показывается как обычный текст: ссылки не открываются, HTML и скрипты не выполняются, а невидимые символы, которыми можно замаскировать заголовок (смена направления письма, символы нулевой ширины, управляющие символы, неверный UTF-8), удаляются.

**Вход.** Для выпусков ничего не нужно; остальное — артефакты workflow сборки, которые GitHub выдаёт только вошедшим пользователям. **Аккаунт GitHub** выполняет вход по коду и QR-коду, который сканируется телефоном. Запрашиваются только права на чтение файлов workflow сборки (Actions) и на создание gist для *Отправить отчёт…*; в остальном токен может читать только публичное. Он хранится в `github_token`, никогда не отправляется с отчётом, а *Аккаунт GitHub* позволяет выйти. После входа Ⓨ (*Поиск*) принимает номер pull request (открытого или закрытого) или коммит (от 7 до 40 шестнадцатеричных цифр) и находит его сборку, только из ветки этого репозитория.

**Установка:** PlayGuard скачивает сборку, проверяет её (размер, SHA-256, записанный GitHub, заголовок NRO), ставит её на место своего `.nro` и перезапускается с ней (если PIN-код задан, он сначала запрашивается). Её окно показывает текущий шаг, размер и скорость загрузки и какую сборку она заменяет; кнопка «Отмена» исчезает, когда сборка ставится на место.

- Список хранится 10 минут и показывается сразу, с указанием его возраста (Ⓧ загружает его заново, как и сам экран каждые 3 минуты, пока идут проверки сборки); пока он загружается, полоса справа в заголовке показывает ход загрузки. Что делает установка, сказано внизу экрана.
- Прерванная загрузка (пропала сеть) продолжается с места остановки при следующей установке той же сборки.
- Артефакты удаляются через 90 дней.

**Возврат.** Заменённая сборка сохраняется (`playguard.nro.previous`): **Вернуться к предыдущей сборке** в том же списке снова меняет их местами, после ввода PIN-кода; она называет эту сборку по версии, pull request и коммиту. Если сборка, установленная отсюда (или обновлением *В PlayGuard*), падает до своего первого экрана, следующий запуск PlayGuard предлагает вернуться к предыдущей сборке на простом текстовом экране, до загрузки чего-либо ещё (A — вернуться, B — всё равно запустить). Возврат запрашивает PIN-код на собственном экране PIN-кода консоли, если он задан (а не на экране блокировки PlayGuard, который как раз может падать); без него запускается установленная сборка. Тот же список в любой момент возвращает к любому выпуску.

**Какая сборка работает:** *О программе › Версия* в режиме разработчика показывает коммит. В заголовке каждого экрана рядом с названием указана работающая версия: у выпуска — в серой метке (`1.2.0`), у любой другой сборки — в янтарной метке с её коммитом, чтобы тестовую сборку никогда не приняли за выпуск.
