Snooping

### Snooping (слежение)

#### Что это такое

Snooping это особенность программы WHDLoad, позволяющая отслеживать и вести журнал событий, доступов к регистрам Cia и Custom. Если активирован параметр Snoop, то все некорректные обращения создадут Ошибку Доступа, а установленная программа будет завершена. WHDLoad выдаст сообщение с причиной сбоя.

#### Custom регистры

Проверяются все попытки чтения и записи custom регистров. Некорректными являются:

- доступы к запрещённым регистрам
- чтение регистров, предназначенных только для записи (Write Only)
- запись в регистры, предназначенных только для чтения (Read Only)
- доступ к регистрам Early Read
- попытка записи байта в регистры (за исключением `bltcon0l` и `aud*vol+1`)

Регистры строба (Strobe) могут быть прочитаны или записаны. Набор Custom-регистров может изменяется между OCS (Old ChipSet - A500, A1000, старая A2000), ECS (Enhanced ChipSet - A600, новая A2000, A3000) и AGA (Advanced Graphics - A1200, A4000). Это полезно для поиска в старых программах ошибок из-за обращений к новым регистрам AGA.

#### Cia регистры

У Cia регистров проверяется только доступ по записи. Это означает, что доступ на чтение для несуществующих регистров в области памяти $bfd000...$bfefff не сможет быть проверен. Для всех обращений по записи, записанное значение WHDLoad сохранит внутри себя. Для некоторых Cia регистров существуют специальные проверки, в зависимости от записываемого значения:

адрес | регистр | проверка
--- | --- | ---
$bfe001 | ciaa.ciapra | запрещена установка Overlay бита #0
$bfe201 | ciaa.ciaddra | биты #6-7 могут иметь любое значение (используется для игрового манипулятора), младшие биты должны быть %000011
$bfe801 | ciaa.ciatodlow | доступы по чтению-изменению-записи (например, bchg) запрещены в случае, если ALARM бит выставлен в ciaa.ciacrb (проверяется только на 68060)
$bfe901 | ciaa.ciatodmid
$bfea01 | ciaa.ciatodhi
$bfed01 | ciaa.ciaicr | доступы по чтению-изменению-записи (например, bchg) запрещены (проверяется только на 68060)
$bfd100 | ciab.ciaprb | биты для MOTOR #7, SELECT #3-6 и STEP #0 должны быть очищены, другие биты могут быть изменены; с помощью этого может быть обнаружен любая попытка доступа к флоппи-дисководам
$bfd200 | ciab.ciaddra | записанное значение должно быть %11000000
$bfd300 | ciab.ciaddrb | записанное значение должно быть %11111111
$bfd800 | ciab.ciatodlow | доступы по чтению-изменению-записи (например, bchg) запрещены в случае, если ALARM бит выставлен в ciaa.ciacrb (проверяется только на 68060)
$bfd900 | ciab.ciatodmid
$bfda00 | ciab.ciatodhi
$bfdd00 | ciab.ciaicr | доступы по чтению-изменению-записи (например, bchg) запрещены (проверяется только на 68060)

#### Как это работает

Если Snoop включен, WHDLoad отмечает в списке перевода диспетчера памяти (MMU) адреса Custom и Cia регистров, как неверные/защищенные по записи. Из-за этого, каждый доступ к Custom или Cia регистрам закончится исключением "Ошибка Доступа". Это исключение будет взято под управление WHDLoad. Вначале, он проверяет, что доступ действителен. Если доступ недействителен, программа будет закончена. Если доступ действителен и если это операция чтения, он будет эмулироваться и выполнение программы продолжится. Если это операция записи то WHDload дополнительно, сохранит значение во внутреннем буфере.
Произойдёт замедление выполняемой программы, так как будут еще обрабатываться исключения и будет производиться эмуляция. Насколько сильно замедлится программа, зависит от типа центрального процессора, типа Chip-памяти (16/32-bit) и выравнивания указателя стека, если Chip-память 32-х битная (есть выравнивание по длинным словам или нет). Это также отличается для типа доступа (байт / слово / длинное слово, чтение/запись). 68030 пишет, быстрее чем, читает (потому что чтение, фрейма стека включает 92 байта, запись - 32 байта), на процессорах 68060 чтение, быстрее, потому что эмуляция для записи, более сложная.

#### Режим быстрого слежения (Fast Snoop)

Параметр Snoop/S активизирует режим быстрого слежения. Доступы по чтению проверяться не будут. Не будет выполняться никаких специальных проверок. Этот способ может быть полезен только для получения содержания Custom-регистров, например, чтобы сделать снимок экрана, используя SP.

#### Сканер Copper List'а

Начиная с версии 13, WHDLoad также может сканировать копперлисты (copperlists). Сканер будет активирован на запись в регистры `coplc`, если активизирован copper dma, или когда установленная программа активизирует coppper dma, записывая в регистр`dmacon`. Сканер следит за копперлистом и подтверждает все инструкции Move, применяя ограничения, наложенные опцией Snoop (OCS / ECS / AGA). Инструкции Skip и Wait (за исключением CEND) будут игнорироваться. Когда он находит недействительные вхождения, установленная программа завершается. Сканер также следит за ответвлениями (`copjmp`), обнаруживает циклы и проверяет до 16 подсписков. Инструкции Move в копперлистах будут сохранены во внутреннем файле регистров, который будет создан при выходе WHDLoad. Сканер не активен в режиме быстрого слежения (Fast Snoop).

#### Проверка приоритета блиттера

Когда активизирована опция ChkBltHog/S, WHDLOAD проверит, что установленная программа не активизирует бит BltHog, записывая в `dmacon` регистр. Приоритет блиттера может создать проблемы на некоторых аппаратных конфигурациях при использовании всех его возможностей (при использовании всех каналов).

#### Проверка размера блиттера

Когда параметр ChkBltSize/S активизирован, WHDLOAD проверит, чтобы блиттер не работал с памятью за пределами области BaseMem. При доступе на запись в `bltsize` или `bltsizh`, он проверяет, установлен ли линейный режим в `bltcon1`. Если линейный режим активен, проверка размера будет отменена. Иначе WHDLoad вычислит первое и последнее слово к доступу для каждого активированного канала прямого доступа к памяти. Если один адрес находится за пределами области памяти BaseMem, то программа будет завершена с выводом окна сообщения. Вычисление предназначено для работы со всеми режимами (ascending/descending, positive/negativ modulos, odd modulos/pointers).
Помните, что режим "line drawing" не проверяется и что все регистры блиттера могут быть перезаписаны коппером, в случае если установлен `copcon`.

#### Проверка ожидания блиттера (Blitter Wait Check)

Когда параметр ChkBltWait/S активизирован, WHDLOAD будет использовать трассировку инструкций на предмет того, что установленная программа действительно правильно ждет окончания работы блиттера, перед его следующим запуском. Whdload использует внутреннюю переменную, которая отображает рабочее состояние блиттерa. Переменная устанавливается, когда производится запись в `bltsize` или `bltsizh`, и сбрасывается, когда происходит чтение из регистра `dmaconr`. При каждой записи в регистр блиттера, проверяется значение переменной, и если значение показывает, что блиттер запущен, то установленная программа будет завершена, а WHDLoad сообщит PC последней запущенной задачи блиттера совместно с реальным доступом.
У данного параметра есть два главных недостатка:
1) использование блиттера через коппер НЕ проверяется;
2) использование перерываний блиттера вынудит процедуру проверки выводить бессмысленные сообщения об ошибках.

#### Планы на будущее

Планируется реализовать такую возможность, как приостановка программы и свёртывание ее в иконку. Для этого отлично подходит Snoop. Поэтому, для обеспечения совместимости в дальнейшем, рекомендую авторам инсталляционных модулей проверять корректность работы ваших патчей с параметром Snoop.

#### Системные требования

Для работы параметра Snoop необходим диспетчер памяти (MMU). WHDLoad также должен использовать MMU, поэтому на машинах с процессорами 68030 необходимо активизировать опцию MMU/S.

#### Ограничения

- 68020 + 68851
  - Эта конфигурация в данный момент не поддерживается
- 68030
  - Неизвестно никаких ограничений
- 68040
  - Эта конфигурация в данный момент не поддерживается
- 68060
  - Инструкция`movem` может обратиться к недействительному регистру, не создав при этом сообщения об ошибке доступа. Это возможно потому, что только первое обращение будет обработано на соответствие действительному регистру.
  - Инструкция`move <Cia/Custom register>,sr` будет выполнена неправильно, если она изменяет часть регистра статуса, принадлежащую супервайзеру, часть супервайзера не изменится.
  - Любая из команд `(ssp)+` или `-(ssp)` совместно с доступом по записи в регистры Cia или Custom не может быть обработана в связи с проблемами фрейма стека. WHDLoad обнаружит такое обращение и завершит работу программы с соответствующим сообщением.
  - Инструкции не должны одновременно обращаться к более чем одному "snooped"-регистру. Это означает, что код, подобный move.b ($dff006), ($bfd800) не может быть обработан и если такой код выполнится, то WHDLOAD выведет сообщение об ошибке доступа.