-------- ------ ----- ---- --- -- - - -- --- ---- ----- ------ ------- --------

       She Stole My Catpressor - a contribution to Undefined party 2026
                               by Speccy.PL

                 for the ZX Spectrum and Timex Sinclair 2068

-------- ------ ----- ---- --- -- - - -- --- ---- ----- ------ ------- --------

   Enjoy an abridged PT3 track "She Stole My Cat" by Pator in just 2048 bytes 
(actually even less because this includes visuals, unpacker and whatnot).

   Credits:
  - code: RCL / SPECCY.PL (also of VVG, Suspend and a few defunct groups)
  - music: Pator / SPECCY.PL (ditto)

                              Under the hood
                             ================

   This is a continuation of my last year's adventures in AY register packing.
Unpacked size is around 15KB of register changes and a 3KB track of 8-bit update 
masks. Music duration is about a minute (3072 frames).
   The way it works: registers are split into 7 update groups with the necessary 
values duplicated (R13 is never duplicated to avoid retrigger), and a bitmask 
of group updates is stored per frame. The trick is finding the best possible 
such grouping (i.e. one that gives the smallest compressed result).
   This is NP-hard, so a practical solution implemented is to score all possible
combinations with a fast but crude scoring function (sort of like a bounding
function in branch and bound) and then measure the best candidates with the
exact UPKR test. If the result does not improve within a certain time window,
we declare what we have to be the best result.

   Visuals are driven by the A, B and C channel volumes, although in a somewhat 
subtle fashion. This is just a three dot walker + a gradual clear.

   The Timex Sinclair 2068 version (why not? I got the hardware) calls different
ROM entry points, outputs to #F5/#F6 AY ports, and skips every 6th update to
accommodate a 60Hz refresh. It also fits in 2048 bytes.

 -RCL, 2026-08-14
------------------ ----- ---- --- -- -  
