### Snooping

#### What it is

Snooping is a feature of WHDLoad which performs validating and logging of accesses to the Custom and Cia registers. If Snoop is activated all invalid accesses will create an Access Fault and the installed program will be terminated. WHDLoad will show a requester explaining the reason of the fault.

#### Custom registers

All read and write accesses to the custom registers are verified. Invalid accesses are:

- accesses to nonexistent registers
- read accesses to Write Only registers
- write accesses to Read Only registers
- accesses to Early Read registers
- byte write accesses (except `bltcon0l` and `aud*vol+1`)

Strobe registers can be read or written. The set of valid Custom registers can vary between OCS (Old ChipSet - A500, A1000, old A2000), ECS (Enhanced ChipSet - A600, new A2000, A3000) and AGA (Advanced Graphics - A1200, A4000). This is useful especially to locate bugs in old programs caused by undefined accesses to new AGA registers.

#### Cia registers

On the Cia registers only write accesses are verified. That means that read accesses to non existent registers in the memory area of $bfd000...$bfefff won't get detected. For all write accesses the written value will be saved internally by WHDLoad. For some Cia registers there are special checks depending on the written value:

address | register | check
--- | --- | ---
$bfe001 | ciaa.ciapra | setting the Overlay bit #0 is prohibited
$bfe201 | ciaa.ciaddra | bits #6-7 can have any value (used for joypad), lower bits must be %000011
$bfe801 | ciaa.ciatodlow | read-modify-write accesses (e.g. bchg) are not allowed if ALARM bit is set in ciaa.ciacrb (only checked on 68060)
$bfe901 | ciaa.ciatodmid
$bfea01 | ciaa.ciatodhi
$bfed01 | ciaa.ciaicr | read-modify-write accesses (e.g. bchg) are not allowed (only checked on 68060)
$bfd100 | ciab.ciaprb | the bits for MOTOR #7, SELECT #3-6 and STEP #0 must not be cleared, other bits can be changed; with that any accesses to the floppy drives will be detected
$bfd200 | ciab.ciaddra | the value written must be %11000000
$bfd300 | ciab.ciaddrb | the value written must be %11111111
$bfd800 | ciab.ciatodlow | read-modify-write accesses (e.g. bchg) are not allowed if ALARM bit is set in ciab.ciacrb (only checked on 68060)
$bfd900 | ciab.ciatodmid
$bfda00 | ciab.ciatodhi
$bfdd00 | ciab.ciaicr | read-modify-write accesses (e.g. bchg) are not allowed (only checked on 68060)

#### How it works

If Snoop is enabled, WHDLoad marks the addresses of the custom and cia registers as invalid/write-protected in the MMU translation tree. Because of this, each access to a custom or cia register will result in an Access Fault exception. The exception handler in WHDLoad handles this exception. First it checks if the access is valid. If the access is invalid the program will be terminated. If the access is valid and is a read operation it will be emulated and program execution continues. If it is a write operation WHDload additional saves the value written to a internal storage.
Because the overhead of the exception and the emulation sequence the program execution will slow down. How much it slows down depends on the CPU type, Chip Memory type (16/32-bit) and Stackpointer alignment if Chip Memory is 32-bit (LongWord aligned or not). It also differs for the access type (Byte/Word/LongWord, Read/Write). On the 68030 Writes are faster than Reads (because on reads the stackframe is 92 bytes on writes 32 bytes), on the 68060 Reads are faster because the emulation for Writes is more complex.

#### Fast Snoop Mode

The option Snoop/S enables the fast snooping. Read accesses will not be checked. No special checks are performed. This mode may be useful to only get contents of the custom registers, e.g. to save a picture using SP.

#### Copper List Scanner

Since version 13 of WHDLoad also copperlists itself will be checked. The scanner will be activated on writes to the `coplc` registers if the copper dma is enabled, or when the installed program enables the coppper dma by writing the `dmacon` register. The scanner follows the copperlist and validates all Move instructions by applying the restrictions caused by the Snoop option (OCS/ECS/AGA). Skip and Wait (except CEND) instructions will be ignored. When it finds invalid entries the installed program will be terminated. The scanner follows branches (`copjmp`), detects loops and checks upto 16 sublists. The Move's in copperlists will be saved in the internal custom register file which is dumped at WHDLoad exit. The scanner is not active in Fast Snoop Mode.

#### Blitter Priority Check

When option ChkBltHog/S is activated WHDLoad will check that the installed program does not enable the `BltHog` bit by a write to the `dmacon` register. The Blitter Priority can cause problems on some hardware configuration in conjunction with large blitter operations (all channels used).

#### Blitter Size Check

When option ChkBltSize/S is activated WHDLoad will check that blitter jobs do not access any memory outside the BaseMem area. On write accesses to `bltsize` or `bltsizh` it checks if the line mode is enabled in `bltcon1`. If the line mode is active it will cancel the size check. Otherwise WHDLoad will calculate the first and the last word to access for each activated DMA channel. If one address is outside the BaseMem area the program will be terminated with a requester. The calculation is designed to work with all modes (ascending/descending, positive/negativ modulos, odd modulos/pointers).
Remember that the line drawing mode will not verified and that all blitter registers can also be written by the copper if `copcon` is set.

#### Blitter Wait Check

When option ChkBltWait/S is activated WHDLoad will use a instruction trace to verify that the installed program does correctly wait for the blitter to finish before starting a new blitter job. It uses a internal variable which represents the working state of the blitter. The variable is set when a write access to the `bltsize` or `bltsizh` occurs and cleared when read access to the `dmaconr` register is performed. On each write to a blitter register the value of the internal variable is checked, if it states a running blitter job the installed program will be terminated and WHDLoad will report the PC of the last started blitter job together with the actual access.
There are two major bottlenecks of this feature. First blitter usage via the copper are not checked and second the use of blitter interrupts will cause the check routine to report errors without necessity.

#### Future

It is planned to implement features like Freezing and Iconifing. For these, Snoop is an essential assumption. Therefore it is recommended for install authors to check their installs with Snoop to secure future compatibility.

#### Requirements

An MMU is required for the Snoop feature. Also WHDLoad must use the MMU, therefore MMU/S must be enabled on 68030 machines.

#### Limitations

- 68020 + 68851
  - this hardware is currently not supported
- 68030
  - no known limitations
- 68040
  - this hardware is currently not supported
- 68060
  - `movem` instruction may access an invalid register without creating an Access Fault exception, this is possible because only the first access will be verified for matching a valid register
  - `move <Cia/Custom register>,sr` will be executed incorrectly if it likes to change the supervisor portion of the status register, the supervisor portion will remain unchanged
  - any `(ssp)+` or `-(ssp)` in conjunction with a write access to a Cia or Custom register cannot be handled due stackframe problems, WHDLoad will detect such accesses and terminate with a appropriate requester
  - instructions must not access more than one snooped register at a time, that means that code like `move.b ($dff006),($bfd800)` cannot be handled, if such code occurs WHDLoad will show an Access Fault requester