                 ░            ░▓▄▄▄▄▄
▄             ▓  ▓▀ ▀▀▀▓▄▄▄▄▄  ▀▓█▄ ▀▀▀████▓▄▄▄▄              ▓
██▓██▄▄▄     ▓░        ░    ▀▀▀▀▒▀█▓▄       ▀▀▀▀██▓██▄▄▄     ▓░
  ░▀▀▀▓███▓▄█▒                  ░  ▒   ▀░         ░▀▀▀▓███▓▄█▒
      ░  ▀▀█ ░                     ░                  ░  ▀▀█ ░


                     Quick Commander v3.22
                         For developers


    For  those  who write programs working with QC or test QC on
their  machines: what QC needs; which configurations beyond a ZX
Spectrum  128K  with an AY and TR-DOS 5.04T it supports, through
which  ports and how; where its file keeps the settings; how the
resident  works  and  how  a  program returns to QC; how QC uses
TR-DOS;  which  file  formats  it  knows.  The  user's manual is
guide_en.txt. All numbers are for the QC 3.22 release build.


    :: What QC needs

    A  Z80  and  IM 1 interrupts (QC sets I = #3F) at 50 Hz: the
player  and  key  waits run on them. While QC runs, the BASIC 48
ROM  is  in  (bit  4  of  #7FFD  always  1): QC calls its PO_MSG
(#0C0A),  MAIN_4  (#1303),  STMT_RET (#1B76), BREAK_KEY (#1F54),
CLEAR_1 (#1EB7), #22B0 and #30A9. Keys come from LAST_K (#5C08),
filled  by  the  ROM's  interrupt  routine; QC puts mouse clicks
there too.

    TR-DOS  ROM  5.03  or  later: QC's addresses are the same in
5.03, 5.04, 5.04T, 5.04S, 5.5H, 6.07+, 6.10E, 6.11E and the SMUC
ROMs; 5.01 differs. Drives: 80 cylinders, two sides; QC counts a
track  as  cylinder*2+side  and  writes  disk  type  #16  to the
catalogue.

    Memory while QC runs:

        #5B00-#5B7F  page table (2 bytes per page)
        #5B80, #5B90 name being typed, mask
        #5B98        code that starts a program
        #5C00-#5D3A  system variables
        #5D3B-#5E51  BASIC loader with the settings
        #5FE8        stack (grows down)
        #6000-#9D7E  QC's code
        #9D7F-#9DFF  file marks
        #9E00-#A6FF  working disk's catalogue (at start: QC's
                     set-up and memory test, run once)
        #A700-#AFFF  catalogue of the disk copied to
        #B000-#BFFF  QC's overlay (since 3.30)
        #C000-#FFFF  window: the buffer, the file viewed

    Code page #D7 (the #7FFD value): from #C000 the launcher and
QC's ZX0-packed code, #FD45-#FF97 a copy of the system variables
and   BASIC   loader   taken   at  load,  from  #FFF0  the  mark
"Residentpresent!".  QC  never pages in 2 and 5; the other pages
(but  the  two overlay pages and, with over 128K, the code page,
see  below)  are  the  Copy and Move buffer, 64 sectors each: on
128K 0, 1, 3 and 7 (256 sectors).
    Overlay  pages  (since  3.30): #D6 and #D4, the .qco's first
16K  from  #C000 of the first, the rest from #C000 of the second
(the  file  up  to  128 sectors). A reset doesn't clear them: at
start  QC  checks  the  header  and the sum and, if it holds its
build's overlays, doesn't read the file. The .qco (on disk: QC's
file  name,  type  q,  "co"  in the start field; on the SD card:
/SYS/TRDBOOT.OVR):  "QCO"; build stamp (word: Fletcher-16 of the
file  from  +5  to  its  last  sector's end, both sums mod 255);
overlay  count  N;  each  stream's  offset (word), then the last
one's  end;  each  stream's  Fletcher-16  to the end of its last
sector  (word).  Then the ZX0 streams back to back, zeros to the
sector's  end. An overlay unpacks to #B000-#BFFF; a stream going
on  from  the first page into the second (one at most) QC copies
to  that area's end first, as the sectors on 48K, and unpacks in
place;  on  48K  each  call  reads  the header and the overlay's
sectors  (to  that  area's  end),  checks the sum and unpacks in
place.
    The  overlays:  0  the picture viewer, 1 the text one, 2 the
sprite  one, 3 ALASM's sources, 4 disk_Utils, 5 Save boot, 6 the
help, 7 the player, 8 the packer (P), 9 the preprocessing: Hrust
and  ZX0  unpacking  (U and files to view), the ZX0 stream check
and  the  module search. The kernel sorts a file to view itself:
the hr2 and HR headers, the ZX0 stream's end mark (the last byte
greater  than  the  one  before  it,  that  one  #55  or #AA), a
picture's  length. Overlay 9 is needed only by a file that looks
packed  and  by  the  music  search: v on a plain file reads one
overlay,  the  viewer's,  while Enter and a click on a file that
isn't a picture read overlay 9 first.


    :: The disk: the VG93 directly

    The Beta Disk ports respond only while the TR-DOS ROM is in:
it  comes  in  on an instruction fetch from #3D00-#3DFF and goes
out on a fetch from RAM. So QC drives the controller with pieces
of  the ROM's own code: it pushes their addresses and enters the
ROM  via  #3D2F  (NOP;  RET), often chaining several. Ports: #1F
command/status,  #3F  track,  #5F  sector,  #7F data, #FF system
register (read: bit 7 INTRQ, bit 6 DRQ).

    System register: #2C plus the drive (bits 0-1): bit 2 = 1 no
reset,  bit  3  =  1  HLT,  bit  5 = 1 as TR-DOS, bit 6 = 0 MFM;
bit 4 = 1  (#3C)  selects  the first side, TR-DOS's even tracks.
Commands:  #08  to cylinder 0, #18 seek (6 ms steps, no verify),
#80/#A0  read/write a sector, #C0 read address, #F0 write track,
#D0 interrupt.

    TR-DOS ROM addresses QC uses:

        #3D2F - the way into the ROM (NOP; RET);
        #3D13 - function 5, read sectors: loading QC, and a
                code file before running it; #13 at the start
                (esxDOS's TR-DOS emulation answers it), under
                esxDOS 1 too (a drive's disk);
        #2A53 - OUT (C),A; RET: VG93 registers, ATM2 port;
        #3EF5 - wait for the end of a command;
        #3FE5, #3FCA - read (INI) and write (OUTI) data;
        #2740 - status and seek;
        #2090, #2093, #2099 - read and write a sector;
        #294A, #2920, #2970 - load a BASIC program;
        #0048 - exit to TR-DOS (key T);
        #3FF0, #3FF3 - OUT and IN for the SMUC clock.

    Speed  (CONFDRV, see "The settings in QC's file"): fast read
and  write  bits per drive; slow waits an extra frame (EI; HALT)
after  each  seek.  The  first  write after a reset or a seek to
track 0 waits ~0.3 s unless QC has seen the disk spinning.

    QC  loads  its own code via #3D13 (as prepared for QC 4.00),
so  it loads wherever TR-DOS works, from its RAM disk too. Until
3.20  the  default  was Nick Patlaenko's fast loader Ursula 2.4:
0.4 s  faster,  but  it drove the VG93 itself, checked no errors
and failed in emulators without those ports.

    Disk  errors:  after 4 failed tries QC shows Retry / Abort /
Ignore; between tries it reads an address (#C0) to fix the track
register,  or  seeks  cylinder  0. The right mouse button held 5
frames during disk work is Break.

    Formatting,  checking  and restoring disks and the catalogue
copy  on  track  161 (disk_Utils, U in the main menu; until 3.22
the  Care  menu,  C:  Keep,  Show, rEstcat, Check disk, Resdisk,
Format)  are  a  QC  overlay  (.qco) with its own VG93 layer: an
unreadable  sector is tried 4 times and counted, without Retry /
Abort  / Ignore; Check rewrites a track where any try failed. In
3.22  Quick Setup's Disk Doctor did this. QC has no autoKeep any
more: all of it matters on real floppies only.

    QC doesn't see TR-DOS 6.1xE's RAM disk: it is reachable only
via #3D13, and QC drives the VG93 directly.


    :: QC under esxDOS

    esxDOS  0.8.5+  (tested: 0.8.9) on a DivMMC (ZX-Uno and Next
in  esxDOS  mode  untested) emulates TR-DOS on the SD card's TRD
images: it traps #3D13 and the ROM pieces QC calls via #3D2F and
runs  them  itself  (its  table  has 85 TR-DOS ROM addresses for
#3D2F;  another  gives a red border and BASIC 48). QC works with
it as with a Beta Disk.

    QC  (and  Quick Setup) detects esxDOS at start by its TR-DOS
emulation's  answer:  #3D13's  function #13 copies 16 bytes from
#0370  (TR-DOS's  version line) to #5CDD. A TR-DOS ROM gives its
own;  esxDOS  serves ROM reads (function #13, the LDIR at #180D)
from  copies  of  four  places  (#0370, #1803, #0013, #2A09; any
other:  green  border and DI: HALT), and after its copy "5.04T*"
comes  its own code: the seventh byte is #CD (CALL), while every
TR-DOS  ROM  QC  knows  has  #0D  or  text there. So QC sees the
emulation  at  work, not the DivMMC ROM (a DivMMC with automatic
paging  off  is  no esxDOS), and writes no DivMMC port; esxDOS's
#3D13  selects its RAM bank 3 (its TR-DOS bank) itself, so #3D2F
works after it.

    Under  esxDOS  (detected first at start) QC: exits to TR-DOS
(T)  not  via  #0048,  absent  from  esxDOS's table, but as when
running a program (resident kept, memory from #5D3B up cleared),
to  esxDOS's  M_AUTOLOAD  (RST  8,  #90)  with A = #FC: esxDOS's
TR-DOS  starts as after a reset, and RETURN there gives BASIC 48
(with  QC's code left in memory it gave esxDOS's browser); for a
drive  with  no  image (a command to it never ends under esxDOS)
first  calls  #3D13's  function 1 and by bit 7 of the controller
status  says  "No Disk."  at  once;  turns  the  SMUC  clock off
(CONFIG2  bit 2 reset at start, the clock unread: the SMUC ports
respond  only  while the TR-DOS ROM is in, and the pieces #3FF0,
#3FF3  aren't in esxDOS's table); doesn't probe for Scorpion and
KAY  memory  (on a +2A/+3 #1FFD selects the ROM: after the probe
ROM 1 replaced BASIC 48). esxDOS doesn't write a sector past the
end of a TRD image cut after its last file, and the status shows
no  error  bit: QC asks Retry, Abort, Ignore as for other errors
(only lost data, bit 2, is retried silently). TRD images have no
write protection in esxDOS 0.8.9.

    QC  as esxDOS's TRDBOOT.BIN (in the kit since 3.21): when an
image   started   from   esxDOS's   browser   has  no  boot  and
SYS/CONFIG/TRDOS.CFG  has  AlwaysBoot=1,  the  TR-DOS  emulation
loads  /SYS/TRDBOOT.BIN  at #6000 (#4000 bytes at most) and runs
it.  QC's TRDBOOT.BIN (16304 bytes) is built as the ROM version:
its code at #6000 pages #D7 in, copies QC's code file, the saved
system variables and the BASIC loader with the settings to #C000
and  jumps  to the launcher, as if QC were loaded from disk. The
settings are the build's until Quick Setup rewrites the file via
the esxDOS API (RST 8: F_OPEN, F_SEEK, F_READ, F_WRITE) with its
own  QC  and  the  old  file's settings (another boot is renamed
TRDBOOT.NAV  by  F_RENAME; the file is written anew: F_OPEN with
FA_CREATE_AL).  Since  3.22  QC's  code file and saved variables
follow  the  code in Quick Setup's file, read to #C000 of page 1
on  128K  (main memory on 48K); from them Quick Setup makes QC's
file,  TRDBOOT.BIN and the ROM image (before, the kit's disk had
trdboot.C and qc_rom.C). After each call it reselects DivMMC RAM
bank  3  (OUT (#E3),3): esxDOS's RST 8 from a program leaves its
bank  0  selected,  and  the  emulation's  #3D2F  jumps into the
selected  bank  (its  #3D13  selects  bank  3  itself); so Quick
Setup's  menu works after card access as before. On a disk error
Quick  Setup  under  esxDOS  asks  Retry, Abort, Ignore, but any
answer is Abort: TR-DOS takes it via #3F7E, absent from esxDOS's
table.  It  selects  a  drive as QC does, skipping BASIC routine
calls  (POP  AF,  RET  at  #5CC2):  a  drive with no image gives
"No disk."  at once (through its TR-DOS error trap, the select's
"no disk"  would  leave  the emulation where its #0000 and #3D00
reset the machine).


    :: The extended memory

    QC  detects  memory at every start, interrupts off. First it
checks  for  128K:  it pages in page 1 (#7FFD = #11) and sees if
page  0 (#10) changed. If not, it is 48K (or #7FFD is locked: QC
run  in 48K mode), and QC tries only ZX-Evolution's #F7F7: there
the  clock  must  leave  its  #EFF7  as is (see the Gluk clock).
Otherwise  it  tries the ports in order; the first that responds
tells the machine:

        port   machine                page bits
        #F7F7  ZX-Evolution           3-7, inverted
        #FFF7  ATM Turbo 2+           3-5, inverted
        #AFF7  Pentagon 4096          0, 1
        #1FFD  Scorpion, KAY          4, 6, 7
        #DFFD  Profi                  0-2
        #FDFD  ATM1                   0-2
        #7FFD  Pentagon 1024          5 (with Caps shift)
        #7FFD  128K, Pentagon 512     0-2, 6, 7

    The  ATM ports come first, with bits 0-2 of #7FFD (bits 6, 7
select  no  page there). ZX-Evolution answers both, but only its
x7F7  port  (#F7F7:  an  8-bit  page number, bits 0-2 still from
#7FFD) pages all 4M; if #F7F7 finds 1024K or less, it is an ATM.
Pentagon 4096 (#AFF7: "Pentagon 4M" in QC since 3.04; ALASM 4.46
has  its driver) comes after them: ZX-Evolution's BaseConf takes
#AFF7  for  its  #EFF7  (any port with A12 = 0, A8 = 1, low byte
#F7,  outside TR-DOS), where a 0 turns on its Pentagon 1024 mode
and  turbo, in which its ATM ports page nothing: QC 3.11, trying
#AFF7  first,  saw 512K there. Scorpion GMX (#DFFD with bit 4 of
#1FFD)  and  GitHub's  Pentagon-4096  (#7FFD, #1FFD and #DFFD as
configured) aren't supported.

    Counting pages: for each combination of port values QC saves
the byte at #C000, zeroes it and takes the pages where it stayed
zero  (non-zero:  the  same page under another number); then all
bytes are restored, so memory contents, e.g. a RAM disk, survive
a start (not Copy and Move). QC uses 64 pages at most (1024K, as
3.11:  a  whole  disk  copies  with 40) but counts all: the mode
window shows the machine (zx - 48K and 128K, pen - Pentagon, evo
- ZX-Evolution, atm - ATM1 and ATM2, k/s - Scorpion and KAY, pro
-  Profi,  +2/3  -  +2A  and +3: only they have bit 0 of the 48K
ROM's  byte  #0B53 = 0) and all its memory, e.g. "evo 4096k". On
Pentagon 4096 the probe finds 128 pages (bits 0, 1 of #AFF7 with
bits 0-2, 6, 7 of #7FFD): "pen 2048k".

    The  page table (#5B00): 2 bytes a page, the extended port's
value  and  #7FFD's;  the buffer's pages first after the start's
reordering,  then  the  overlay pages and the code page (see the
code page below). On Pentagon the page bits are added to #7FFD's
value;  elsewhere  QC  writes  the extended port, then #7FFD. On
ATM2 and ZX-Evolution the value is inverted and written to #FFF7
or  #F7F7 via the TR-DOS ROM (#2A53): the ATM ports respond only
while it is in (as in Real Commander).

    Keys  held at start: W - 128K only (#7FFD alone); Caps shift
-  Pentagon  1024  by bit 5 of #7FFD (without it 512K is found).
Where  bit  5 of #7FFD is the lock (all but Pentagon 1024), Caps
shift  at  start  locks  the port till a reset: QC thinks it has
128K, but every page is page 0.

    Page  8  is used only if CONFIG2 bit 5 is 1 and the BASIC 48
ROM  has  no JP (#C3) at #0008. Scorpion's has: its page 8 holds
the shadow monitor.

    QC  keeps  the  code page (the resident's) out of the buffer
when  there is over 128K (until 3.30 if CONFIG2 bit 1 was 1); on
128K (and with W on Scorpion, Profi, ATM and ZX-Evolution) it is
the  buffer's  last  page, and Copy, Move, P, U of a big file, a
file  over  48K  or  an ALASM source viewed and a gigascreen may
overwrite  it. The code page is the one #D7 pages in: 7 on 128K,
Scorpion,   Profi,   ATM   and   ZX-Evolution,  31  on  Pentagon
512/1024/4096,  23 on KAY 1024. QC finds it at start: the memory
test  marks  each page with its page table entry's number and by
the  marks knows the entries of the code page and of the overlay
pages  (#D6,  #D4);  then  the  table is reordered: the buffer's
pages first in their order, after them the overlay pages and the
code  page,  so that a logical page number is its entry's (until
3.30 the memory driver skipped the entries 2, 5, 6, 7 and 8, the
overlay page and the code page swapped into 6 and 7). Until 3.20
the  table's  page  7  itself  (#17)  was  skipped,  leaving the
resident  exposed to Copy and Move on Pentagon 512/1024/4096 and
KAY  1024.  Before  running  a program or going to TR-DOS (t) QC
checks  the resident: the launcher at the page's start, the mark
and  the  Fletcher-16  of  QC.C  past  the  launcher to its last
sector's end (the build writes it into the BASIC loader); if any
of  them  is  off,  QC wipes the mark's first and last bytes, so
that a program doesn't go back into a spoilt resident. Save boot
checks the same.

    48K:  the  Copy and Move buffer is the #C000 window (16K, 64
sectors); files are read for the viewers and the music search up
to 16K, unpacked up to 16K too.

    QC doesn't page the +2A/+3's memory by #1FFD: it works there
as  on a 128K (under esxDOS; the panel shows "+2/3"). Its delays
are  counted  loops, shorter with a turbo; the machines' timings
it knows only for a .bsc's border (see the pictures).


    :: The Shadow RAM and the Magic button

    Quick Setup puts QC into the shadow RAM (the cache; its item
5): turns it on by reading port #FB, writes both 16K halves of a
32K  shadow  RAM  (selected  by bit 4 of #7FFD), turns it off by
reading port #7B; it tests for one by writing a byte. Until 3.30
QC's  loader  wrote  the  resident  there if I was held while QC
loaded from disk (the same to both halves).

    Both  halves  are  the same: #0000-#003E zeros (NOPs: Gluk's
Reset  Service  enters  the  shadow  RAM at 0 and runs on to the
resident),  #003F-#0067  the resident (41 bytes, its JR at #0066
the   NMI   entry),  from  #0068  a  copy  of  the  code  page's
#C000-#FF97.

    Magic  must give an NMI with the shadow RAM in; Gluk's Reset
Service  enters it at 0, leading the same way. The resident sets
the  stack  to  #5FE8,  pages #D7 in, copies #0068-#3FFF back to
#C000,  clears  the  screen  and  border and jumps to #C000. The
launcher  restores  the  system  variables  and the BASIC loader
(#5C00-#5E52),  unpacks  QC to #6000 and starts it; QC turns the
shadow  RAM off, takes the settings from the CMOS, as on a start
from  ROM; the overlays from pages #D6 and #D4 if they are whole
there,  else  from  the  input  disk if it has the .qco, else QC
offers  to load them at a catalogue read (they aren't written to
the shadow RAM).


    :: QC in ROM in place of Basic 128

    QC_3_22.rom  (16K)  replaces  the  Basic 128 ROM, i.e. ROM 0
(bit 4 of #7FFD = 0); ROM 1 must be BASIC 48, and a Beta Disk is
needed.  Settings come from the CMOS; without one QC starts with
the build's (boot mode, drive A).

    The  image:  from  #0000 DI and NOPs up to #0037, so both an
entry  at 0 and an IM 1 interrupt at #0038 start QC. From #0038:
stack #5FE8, border 0, attributes cleared, #7FFD = #C7 (the code
page, as #D7 but keeping QC's ROM in; until 3.20 #07, page 7, so
on  Pentagon  512/1024/4096  and  KAY  1024  QC sought its code,
settings  and  resident  in another page), the image copied from
#005B to #C000, a jump to the launcher. From #005B: the launcher
and  packed  code  (to  #C000); from #3DA0: the system variables
#5C00-#5D3A  with  the  descriptor of the file "QC 3.22" and the
BASIC  loader  with  the  settings (to #FD45). No NMI entry with
QC's ROM in: #0066 is inside the launcher.


    :: The CMOS clock

    CONFIG2  sets  up  the clock: bit 2 use the CMOS, bit 3 Gluk
(1) or SMUC (0), bit 4 read and write (0: clock only).

    Gluk:  OUT  (#EFF7),#80  (bit  7 opens access), the register
number  to  #DFF7, data IN or OUT via #BFF7, then OUT (#EFF7),0.
The  port  can't  be  read, and QC writes all of it, every frame
while waiting for a key: its other bits, if any, become 0. Where
an  ATM  port  pages  (ZX-Evolution's  #F7F7 or ATM2's #FFF7; on
ZX-Evolution  also  with  #7FFD  locked, QC run in 48K mode, and
with W), it writes #94 and #14 instead: bit 2 = 1 keeps Pentagon
1024  mode  off (in it page bits 3-5 come from #7FFD, and buffer
pages  from  8  up  fall  on  the  first eight), bit 4 = 1 keeps
3.5 MHz, as the boot menu sets them for TR-DOS.

    SMUC:  the ports respond only while the TR-DOS ROM is in; QC
reaches  them through pieces of the SMUC ROMs: OUT (C),A; RET at
#3FF0  and  IN  A,(C);  RET  at  #3FF3. Read: register number to
#DFBA,  then IN from #DFBA. Write: register number to #DFBA, #F7
to  #FFBA,  data to #DFBA, #77 to #FFBA. These pieces are in the
SMUC TR-DOS ROMs and 6.10E/6.11E but not 5.04T: don't choose the
SMUC clock with 5.04T.

    The  clock:  QC  reads  register #0B; #FF means no clock, no
time  shown.  If writing is allowed, QC sets #0B = %00000010 (24
hours,  BCD)  while  reading  and restores it after. While bit 7
(UIP)  of  register  #0A  is  1, the frame is skipped. The time:
registers 4, 2, 0 (hours, minutes, seconds, BCD).
    At start, before the CMOS settings, QC checks for the clock:
register  #0B is read for a frame; if it changes even once or is
#FF,  CONFIG2 bit 2 is reset in memory, and QC works without the
CMOS  until  the  next start. On a 128 or +2 without a clock its
ports read screen bytes (the floating bus): until 3.21 QC showed
??:??:?? from them.

    QC's cells: #10 the input drive (0..3); #15 CONFIG (bits 0-2
output  drive,  4 fullcat off, 5 QC's mark, 6 no looping, 7 boot
mode);  #16  the  cursor's file number + 1 (1..#80; 0: none). QC
writes them at every cursor redraw if CONFIG2 bits 2 and 4 are 1
and  reads them, with the same bits, only on a start from ROM or
by  Magic; CONFIG is taken from #15 only if its bit 5 is 1. Cell
#10  is  shared  with Real Commander 1.96 and TR-DOS 6.05E+ (the
autostart  drive).  With  its  bit  7 set (Mr Gluk Reset Service
6.3+: don't keep the drive) QC leaves #10 alone, as Gluk does.


    :: The Kempston mouse

    Ports:  #FBDF X, #FFDF Y (inverted; QC inverts it so Y grows
down),  #FADF buttons in bits 0-2 (0: pressed): bit 0 right, bit
1  left,  bit 2 third, as on a Kempston mouse. ZX-Evolution (and
MAME's  pentevo)  has  the  left  one  in  bit 0:  with  CONFIG2
bit 7 = 0  QC  swaps  bits  0  and  1  back (Quick Setup: Mouse:
swapped). The wheel isn't read. A button counts as pressed after
3 unchanged frames.

    QC  looks for the mouse at start: it reads the buttons for a
whole  frame (1202 reads of #FADF), and if any reads as pressed,
the  mouse  is turned off; so a held button disables it. Without
an  interface  the  ports  read  #FF on most machines: the mouse
stays  on  but  does  nothing. On a grey 128 or +2 they read the
floating bus: screen bytes while it is drawn, #FF in the border;
within  a  frame  some screen byte almost always has a 0 in bits
0-2,  so  the  mouse  is  turned  off  too.  Unreal Speccy needs
SwapMouse=1 for the Kempston button order.


    :: The AY

    The  player  (Sergey  Bulba's PTSPlay since 3.30, PTxPlay in
3.20-3.22)  works  with  one  AY  or  two  (TurboSound, NedoPC's
standard:  #FF  to  #FFFD selects the first AY, #FE the second):
#FFFD  register  number,  #BFFD data. Registers 0-12 are written
every frame, 13 only when changed. The meters read registers 0-5
and  8-10 from the AY (both TurboSound AYs on the same bars). At
start  QC silences both AYs: mixer #FF, volumes 0. C changes the
order of the channels written to the AY: ABC, ACB, BAC.


    :: The settings in QC's file

    The file "QC 3.22" (type B, start and length 279) is a BASIC
loader:  line  1  CLEAR  24575: RANDOMIZE USR 23925 (the numbers
hidden  behind  dots),  then  the  settings,  the loader and the
depacker;  from  the  3rd  sector, the packed code. The settings
start  at  file  offset  23  (#17),  35  bytes;  after  loading,
#5D52-#5D74.  The  packed  code's  sector  count is at offset 74
(#4A):  the  file  length depends on the build; take it from the
catalogue.

    The  same  loader,  the settings at the same offset from its
line,  is  in  QC's  ROM  image  and TRDBOOT.BIN (their last two
sectors:  #3E80  bytes  after  the boot code), in the resident's
code page (#D7, at #FE80) and in the Shadow RAM (at #3EE8 of the
cache, in both of its halves). Quick Setup finds it there by the
loader's  line  (on  a disk, in boot.B's first sector) and takes
its settings, if 3.20 or later, for the QC it writes there.

    These  bytes with defaults and file offsets (labels as in QC
3.11's  source; in 3.30 Config, Config2, DriveConfig, TextModes,
FileColors,    OtherColors,    Colors,    ViewerTextColor    and
ViewerInfoColor in src/loader/settings.asm):

        ;0-2: output drive (kept for a return)
        ;3: unused in 3.20 (3.11: H packs with LE)
        ;4: 1 - fullcat off, 0 - fullcat on.
        ;5: 1 - QC config ID, 0 - RC config ID.
        ;6: 1 - play without loop, 0 - loop on.
        ;7: 1 - boot mode, 0 - commander mode.
CONFIG  DB %10111000                        ;#17

        ;0: not used (till 3.20: 1 - fast load QC, Ursula).
        ;1: not used (till 3.30: the code page off the buffer).
        ;2: 1 - use CMOS, 0 - don't use.
        ;3: 1 - Gluk CMOS, 0 - SMUC CMOS.
        ;4: 1 - read & write CMOS, 0 - clock only.
        ;5: 1 - use page 8 (not on Scorpion), 0 - never.
        ;6: 1 - key click on, 0 - off (S, 3.30).
        ;7: 1 - Kempston mouse buttons, 0 - swapped.
CONFIG2 DB %11111111                        ;#18

        ;0: 1 - fast load, 0 - slow load: Drive A.
        ;1: 1 - fast save, 0 - slow save: Drive A.
        ;2: 1 - fast load, 0 - slow load: Drive B.
        ;3: 1 - fast save, 0 - slow save: Drive B.
        ;4: 1 - fast load, 0 - slow load: Drive C.
        ;5: 1 - fast save, 0 - slow save: Drive C.
        ;6: 1 - fast load, 0 - slow load: Drive D.
        ;7: 1 - fast save, 0 - slow save: Drive D.
            ;D C B A
CONFDRV DB %11111111                        ;#19

        ;0-1: text viewer W: 0 - cut, 1 - wrap, 2 - words.
        ;2-3: text viewer M: 1 - colours, 2 - codes as
        ;     signs, 0 - codes hidden.
        ;4-5: music view C: 0 - ABC, 1 - ACB,
        ;     2 - BAC.
TXTMODE DB %00000100                        ;#1A
SET_VER DB 1                                ;#1B

COLORSF DB #47,#07,#43             ;B C s   ;#1C
        DB #45,#45,#45,#45,#45,#45 ;m M - - S w
        DB #44,#44,#44,#44         ;W t T d
        DB #02,#42,#42,#42,#42     ;p z Z r h
        DB #05,#05,#05,#05,#05     ;H R a A X
COLORSO DB #04,#01,#06             ;scr del oth ;#33
COLORS  DB #5F,#78,#05,#30                  ;#36

    CONFIG:  bits 0-2 the output drive: QC keeps it when running
a  program  (in  the  resident  and the CMOS); a start from disk
takes  both drives from TR-DOS's #5CF6, not from the file. Bit 3
unused  since 3.20. Bit 5 = 1 tells QC's settings byte from Real
Commander's:  a  CONFIG with bit 5 = 0 isn't taken back from the
resident  or the CMOS (the drives and the cursor are). The other
bits  are  default  modes.  CONFIG,  CONFIG2  (bit  6:  S in the
viewers)  and TXTMODE are the only settings bytes changing while
QC runs.

    CONFIG2:  bit  0  unused  (until 3.20 what loaded QC's code:
Ursula  or  #3D13);  bit 1 unused (until 3.30 keep the code page
out  of  the buffer with over 128K: since 3.30 QC always does; 1
in  the  settings);  bits 2-4 the CMOS clock (with bit 4 = 0 the
settings  are neither written to the CMOS nor read from it, only
the  clock is shown); bit 5 page 8; bit 6 (since 3.30) key click
(S  in the viewers; Quick Setup's Key click; unused before, 1 in
all settings). See "The extended memory" and "The CMOS clock".

    CONFDRV:  read  and  write  speed  per drive: fast is ~1.5-2
times  faster  but  may  write  wrongly on slow drives (under an
emulator always choose fast); slow writes correctly on any drive
thanks to an extra frame's delay after head positioning.

    TXTMODE  (since  3.30):  the  viewers'  modes,  as  the text
viewer's W and M and the player's C step them: bits 0-1 wrapping
(0  long  lines  cut,  1  wrapped  at  the  screen  edge, 2 at a
separator),  bits 2-3 colour codes (1 colours, 2 codes as signs,
0  hidden), bits 4-5 AY channel order (0 ABC, 1 ACB, 2 BAC). The
viewers  start  in these modes, and W, M and C change them here,
so  Save boot saves them; Quick Setup sets them (Text wrap, Text
codes,  Tunes).  SET_VER  (since 3.30): the settings version, 1.
Quick  Setup  takes  settings of its version as they are, others
(3.20..3.22's,  KEEP_TS's  track 159..162 here) with the default
TXTMODE  and  its  SET_VER.  Until  3.30  these  two  bytes were
KEEP_TS,  where QC kept the catalogue copy for Keep and autoKeep
until  3.21 (#A107: sector 7 of track 161); disk_Utils keeps the
copy there.

    COLORSF:  colours  of 21 file types, in reverse order of the
panel's  type  table  ("XAaRHhrZzpdTtWwSXXMmsCB"); bytes 6 and 7
(.v  and .V until 3.20) unused. COLORSO: colours of screen files
and  fonts  (known  by  length:  6912, 6144, 13824, 2048, 768; a
gigascreen  also  by  type i), of deleted files, of other types.
COLORS: QC's own: the cursor on a marked file, marked files, the
viewer's  default  text, its info line. 24 file colour groups in
all.

    A  setup  program  can recognise QC's file by its BASIC line
(file  bytes  4-21: FD 2E 0E 00 00 FF 5F 00 3A F9 C0 2E 0E 00 00
75  5D 00) and LD SP,#5FFF (#31 #FF #5F) at the start of the 3rd
sector.  The settings layout is unchanged since 3.11. In the ROM
image they start at offset #3EF2.


    :: The resident and the return to QC

    The  resident  is the whole code page #D7: the launcher with
QC's  packed code (from #C000), the copy of the system variables
and  the  BASIC  loader  with the settings (#FD45-#FF97) and the
mark  "Residentpresent!"  (#FFF0-#FFFF), written at every start:
by  it  TR-DOS  6.10E+  start  QC  after  a reset. QC checks the
resident  by the word #FF31 at #C000 of page #D7 (the launcher's
LD  SP,#5FFF)  and  the  mark's last two bytes ("t!" at #FFFE: a
program's  stack  spoils  them first): this is "res" in the mode
window.

    Why  #D7,  not #17: until 3.10 QC, like Real Commander, kept
the  resident  in  page  #17;  since  3.11  it  is in Pentagon's
standard  page  #C7,  for TR-DOS 6.05E+ and 6.10E to find (bit 4
selects  only  the  ROM,  so #D7 is the same page as #C7). Where
#7FFD  ignores  bits 6 and 7 (128K, Scorpion, Profi, ATM), #D7 =
#17  =  page  7; on Pentagon 512/1024 it is page 31, on KAY 1024
page 23, and a program paging in #17 won't find QC there.

    Returning to QC from a program:

        LD BC,#7FFD
        LD A,#D7 ;(not #17!!!)
        OUT (C),A
        LD HL,(#C000)
        LD DE,#FF31
        XOR A
        SBC HL,DE
        JP Z,#C000
        LD H,A
        LD L,A
        PUSH HL
        LD A,#10
        OUT (C),A
        JP #3D2F

    If  the resident is intact, JP #C000 starts the launcher: it
sets  the  stack,  restores  the  system variables and the BASIC
loader  (#5C00-#5E52),  unpacks  QC  to  #6000  and  starts  it.
Otherwise  page 0 and the BASIC 48 ROM come in, 0 is pushed, and
JP  #3D2F  (NOP; RET in the TR-DOS ROM) goes to the TR-DOS ROM's
address  0:  TR-DOS 6.10E+ find "Residentpresent!" and start QC,
others  just start. The program's stack must be below #C000 (the
PUSH  runs  with  page  #D7  in),  and  interrupts  are best off
beforehand:  the  launcher  disables  them  only with its second
instruction. QC writes #7FFD alone, so a program should zero the
extended port (#1FFD, #DFFD, #FDFD) before leaving.

    To return, a program must leave page #D7 from #C000 to #FF97
and  the mark from #FFF0 intact. On 128K that page is the second
screen  (#C000-#DAFF):  a  program  showing  it  overwrites  the
resident.  A  program run in 48K mode (R) can't return: #7FFD is
locked.

    What  QC  keeps  when running a program: before the start it
writes  the cursor's file number + 1 (#FD42), CONFIG (#FD43) and
the  input  drive  (#FD44)  into  page #D7 and sets LaunchedFrom
(#C01E)  =  2.  On  a  return through the resident QC takes them
back: the cursor if 1..#80, CONFIG if its bit 5 is 1 (the output
drive  from its bits 0-1 anyway), the input drive from the third
byte.  So both drives, the menu, the cursor, fullcat and looping
come  back.  LaunchedFrom: 0 started from disk, 1 from ROM or by
Magic, 2 back from a program.


    :: Running programs

    Before  any  run  QC writes what it keeps into the resident,
pages  in  page  0 and the BASIC 48 ROM (#7FFD = #10, unlocked),
sets  CURCHL  = #5D26 and HL' = #2758, puts the file's catalogue
entry  into  the  TR-DOS  descriptor (#5CDD-#5CEC) and its track
into  #5CF5  (the  head  goes there), DosHook (#5CC2) = RET, the
current  drive  into  #5CF6, #5D19, #5CF8, #5CF9 and bits 0-1 of
#5D16,  and  enables  interrupts  (IY  =  #5C3A, IM 1, I = #3F).
System  variables:  LAST_K = 0, REPDEL = 16, REPPER = 1, FLAGS =
#CD, FLAGS2 = 0, P_POSN = 0.

    A  code  file is loaded at its start field and run there, no
questions  asked  (until  3.20 the load and start addresses were
asked  on  line 23); one starting in the screen (#4000-#5AFF) is
shown  by the viewer, as by V; other types but BASIC aren't run.
The  screen is cleared (border and attributes 0), #5D3B-#FFFF of
page  0  zeroed, the sectors read by #3D13 (not past #FFFF), and
the  program started via PUSH IX; JP #3D13, stack #5FE8. A start
below #4000 lands in the TR-DOS ROM.

    A  BASIC  program:  white  border, CLEAR (#1EB7) with RAMTOP
#FF00,  #5D3B-#FE4B zeroed, the file loaded by the TR-DOS ROM by
its  descriptor,  no catalogue search (so deleted and same-named
files  run  too), the autostart line from the bytes #80, #AA and
the  line number after the program, the run started via STMT_RET
(#1B76).

    A  48K  mode  run (R in the main menu): #7FFD = #30 (page 0,
BASIC  48  ROM,  bit  5 the lock), the extended port at page 0's
value. On Pentagon 1024 bit 5 is a page bit, not the lock.

    Exit  to  TR-DOS  (T):  border  7, P_RAMT = #FFFF, a jump to
#0048 of the TR-DOS ROM; the resident is checked first, as for a
program run (a spoilt one's mark wiped).


    :: How QC works with TR-DOS

    QC  doesn't  use  TR-DOS's  catalogue  and file routines: it
reads  and  writes  the catalogue's 9 sectors itself through the
VG93.  From  the  TR-DOS  ROM  it takes the functions of #3D13 5
(loading  its  own  code  and code files) and #13 (at the start:
esxDOS's  TR-DOS  emulation  answers  it;  under esxDOS 1 too, a
drive's  disk),  BASIC program loading (#294A, #2920, #2970) and
the  exit to TR-DOS (#0048); the rest is pieces of ROM code (see
"The disk: the VG93 directly").

    Geometry:  track D is cylinder D/2, even tracks on the first
side  (#3C  in  the  system  register), odd on the second (#2C).
Sector  E  is  0..15,  as in TR-DOS, numbered E+1 (1..16) on the
disk,  256  bytes;  the  side  in  a  sector ID isn't checked on
reading.  Error  messages  and  file  info show sectors 0..15. A
track  number may be anything up to 255; reads and writes run on
from one track to the next.

    The  disk  size comes from the disk's info sector: the first
free sector's number (#E1, #E2) plus the free sectors (#E5-#E6).
So disks of any size, over 160 tracks too, keep their size.

    QC  doesn't  read the disk type (#E3) and always writes #16;
it has no double stepping or single side. By the code (untested)
this  means:  a  40-track  disk  (#17)  works only in a 40-track
drive,  a  single-sided one (#18, #19) is misread everywhere but
track 0, and after a QC write TR-DOS too takes the disk as 80x2.

    QC  recounts  the  info sector (track 0's sector 8, counting
from  0)  in  memory after every catalogue read and before every
write:  #00 = 0; #E1, #E2 the first free sector and track: after
the  last file with sectors, deleted ones counted (entries of no
sectors  at  0/0 after the files are pictures drawn by names and
take no room), but not before the value already there: what lies
past  the files without an entry stays taken (on disks with data
past  such  entries  the info sector says the disk is full), and
only  Delete  at  the  catalogue's  end  and M move it back (see
below);  #E3  =  #16;  #E4  entries  up  to the catalogue's end;
#E5-#E6  free  sectors  (disk size minus the first free sector's
number);  #E7  =  #10;  #F4 deleted files. So the panel's Files,
Deleted and Free are QC's count, not the disk's numbers. The #10
at  #E7  isn't  checked  on  reading:  QC  shows  a  foreign  or
unformatted  disk  as  is and sets #10 when writing (then TR-DOS
accepts  it too). Other bytes are written back as read (after an
aborted Copy #3F-#C0 are zeros, see below).

    QC's  disk  name has 11 characters: #F5-#FF, to the sector's
end;  TR-DOS's  8  (#F5-#FC).  TR-DOS's  Format  writes zeros to
#FD-#FF;  QC  shows  them as ▒. The name is in the panel's right
column,  changed  by N: bytes not typed over stay, Delete puts a
space. TR-DOS 5.04T's CAT and LIST print the name up to a 0 byte
or  a  byte  with  bit  7  set:  with no zero in #F5-#FF (all 11
characters  typed)  they  print on past it (per TR-DOS's source,
untested).

    The  catalogue: 128 entries of 16 bytes; a name's first byte
0  is  the  catalogue's  end,  1 a deleted file. The panel shows
entries  up  to  the end, deleted ones too; in Full mode (F) all
128,  those  past  the  end  as ▒ in the deleted colour. Deleted
entries  and  those past the end can't be marked. Delete sets 1,
and  if the catalogue's end follows deleted entries, their whole
run  becomes  the  end  (0)  and their room free: the first free
sector  is where the first of them begins, if it has sectors (as
with  TR-DOS's  ERASE  of  the  last  file:  data past that file
without an entry become free; an entry of no sectors, a picture,
leaves it); only the catalogue is written.

    Before each catalogue write (Delete, R, CS+R, N, M, C, G, U,
P,  Save boot) QC reads the catalogue into the second buffer and
compares sectors 0-7 and the disk name (#F5-#FF) with the one in
memory;  the rest of the info sector isn't compared: QC recounts
it.  On  a  difference:  Bad  disk.,  the  command  dropped, the
catalogue  reread. Two disks with the same entries and name (two
empty ones named alike, say) pass, and QC writes the first one's
info sector (its size) onto the second. QC doesn't notice a disk
change  itself:  the catalogue is reread by 1-4 and 5, the third
mouse button and after Bad disk.

    Copy:  files  are  copied  in  marking  order; QC keeps that
order's  table  (129 bytes) in the working disk's info sector in
memory,  #40-#C0  (and  #3F  for unmarked ones). Files are added
after  the  target catalogue's last entry, deleted ones counted,
from  its first free sector: deleted entries aren't reused, same
names  aren't checked. Before copying QC checks that the sectors
suffice  (else  No  Space.  Free:  n) and that there will be 128
entries  at  most (else Cat Over. Free: n); the target's size is
from  its  info  sector.  An  aborted Copy (Abort, No Space, Cat
Over)  zeroes  #3F-#C0 of the info sector in memory (as TR-DOS's
Format  writes  them),  and the next write of the working disk's
catalogue puts zeros there. With one drive QC asks to swap disks
(Insert  OUTPUT,  Insert  INPUT)  and reads the target catalogue
only at the first swap.

    Move (M): from the first deleted file to the catalogue's end
(after  the  first  marked file, if any) all live files are read
and  written  back  to  back from the first free sector; deleted
entries  past that place are gone. After M the first free sector
is  past  the last file, by the entries, as after TR-DOS's MOVE:
data  past  the  files  without  an entry become free. If memory
can't  hold them all at once, the catalogue is written in parts;
aborted (Abort) after a part was written, M writes the catalogue
as  it  left  the  disk:  files moved whole at their new places,
before  the  first  one  not moved a deleted entry over the room
left  (a  copy  of  its  entry,  255  sectors at most), then the
entries as they were; a file whose new copy already lay over its
old place becomes deleted. Merge (G): the marked entries must be
consecutive  in  the  catalogue  (QC  doesn't  check that on the
disk).  The  first entry keeps its name, type, start and length,
only  its  sectors  grow, so the length no longer fits them (see
below).  Over  255  sectors:  the first entry gets 255, the next
marked  one  (with  its  own  name)  the  rest;  the rest of the
catalogue moves up.

    A file's length for View, U and the viewers: the sectors are
the entry's byte 13 (a file of 0 sectors isn't read: back to the
panels). The length field is taken if its high byte is sectors-1
(low  byte  not  0)  or sectors (low byte 0); else the length is
(sectors-1)*256+#FF.  On 48K over 64 sectors count as 64 sectors
and  16383  bytes.  Copy and a code file's start take byte 13 as
is:  a  file  of  0 sectors is copied as an empty entry, and its
start loads nothing.

    Names  and  extensions: the name's 8 characters and the type
(byte  8);  TR-DOS  knows  only the type. QC shows a 3-character
extension:  the type and the start field's two bytes (low, high)
if  both  are #20..#7F (#7F printed as the copyright sign), else
the  type  and  two  spaces. This holds for any type, B too (its
start  is  the program's length): CODE 30000 (#7530), say, shows
as  .C0u.  A  panel line: the name's 8 characters, a narrow dot,
the  type,  the  extension's  two  characters and the sectors (3
digits, leading zeros as narrow dots). Bytes #00-#1F and #B0-#DF
print  as  the  chequered sign ▒, #80-#AF and #E0-#EF as Russian
letters,  #F0-#FF as QC's signs; a deleted file's first byte (1)
is ▒ too.

    How  commands  write  the  extension.  R  writes the type as
typed,  and the two characters into the start field only if both
are printable (#20..#7F); two spaces give #2020 if the extension
was  long  and  leave  the  start alone if it was short; Russian
letters  don't change the start. Masks (CS+L, CS+X, CS+R) are 12
characters:  name, dot (not compared), type, the start's low and
high  byte;  bytes are compared as they are, ▒ is any byte. CS+R
writes  every mask character but ▒ as is, Russian letters too. U
gives  type  X  for  p_X  and z_X, else C, and two spaces in the
start;  if  they are kept, a code file (C) gets start #8000 (the
real one is lost at packing: the packed file's start field holds
its extension). Copy keeps the entry as is.

    A  file's  colour in the panel, in checking order: a deleted
file  the  deleted colour; a length field of exactly 6912, 6144,
13824,  2048  or  768  the  picture colour, even before the type
(11136   and   49152   aren't  among  them);  type  i  (.img,  a
gigascreen),  p_i  and  z_i  the picture colour too; type p or z
with  "_"  in the start's low byte the colour of the type in the
high  byte;  else the type is looked for (case-sensitive) in the
table  "XAaRHhrZzpdTtWwSXXMmsCB",  and  one  not  found gets the
other files' colour (as do TR-DOS's D and #). The table's types:

        B  BASIC               p  Hrust
        C  code                z  .zip, .zx0
        s  .scr, .scl          Z  ZXZip
        m  ProTracker 3        r  .rar, .rzx, .rom
        M  ProTracker 2        h  Hrip
        S  Sound Tracker       H  ALASM
        w  .wav                R  Storm
        W  ZXWord              a  Masm, ZASM
        t  .txt                A  TASM, GENS
        T  .TXT                X  Xas
        d  .diz, .doc

    QC  acts  on the type only for B (Enter runs BASIC, the boot
list,  Save  boot)  and p_X, z_X (colour and U's type); it knows
pictures by length, packed files and music by contents.

    Russian  letters:  Edit switches the YAWERTY layout, letters
go  to  #80-#AF and #E0-#EF (cp866); Ё can't be typed. Only CS+R
and  U  write  them  into  the  start field: R and the extension
display  take  only  #20..#7F  there.  TR-DOS  prints such names
through  BASIC's  PRINT  (#80-#8F  block graphics, #90-#A4 UDGs,
#A5-#FF keywords) and compares names byte for byte.

    BASIC  files: the boot list has type B only, without deleted
ones, in catalogue order. A file runs by its catalogue entry, no
search,  so deleted and same-named files run from the file menu;
the  autostart line is the two bytes before WORKSP, which TR-DOS
takes  from  the  #AA  and the line number after the program (QC
doesn't  check the #AA itself). Save boot writes boot.B from the
resident  (its  start  and  length the BASIC part's, its sectors
those  and QC.C's) in place of the catalogue's first boot.B (the
one TR-DOS runs): over it and the free sectors after it if it is
the  last file; over it, the rest a deleted file after it, if it
is  as  long  or  longer (with the catalogue full the old length
kept in the entry); a shorter one marked deleted and the new one
added  at the end (until 3.21 always at the end, with the start,
length  and  sectors  of  the file QC was loaded from). The .qco
goes beside it by the same rules.

    TR-DOS  variables:  QC  reads  #5CF6 (both drives on a start
from  disk)  and  #5CF4,  #5CF5, the code's place on disk, which
TR-DOS  leaves  after  loading the BASIC part (a program loading
QC's  file  itself  must  leave  them so); #5CE6-#5CEA (a file's
entry)  it  fills  to run a code file. DosHook (#5CC2) = POP AF;
RET:  TR-DOS's  calls of BASIC routines (via #2F72) are skipped,
so the BREAK test never fires in the ROM pieces QC calls; before
running  a  program  QC  puts  RET  there. The drives' step time
(#5CFA-#5CFD)  =  8: bit 7 = 0 (TR-DOS doesn't test the drive on
selecting  it), 6 ms steps; seeks by the pieces at #2740 step at
30 ms (#1B).

    AutoKeep's  mark  (16 bytes "Quick Commander " at offset #C8
of  the  info  sector)  was written by QC until 3.21; since 3.22
nothing  writes  or  reads  it.  The catalogue copy on track 161
(sectors  7-15,  counting  from 0: Keep, Show, rEstcat) is kept,
shown and restored by disk_Utils (the track formatted with those
sectors  only; in 3.22 by Quick Setup's Disk Doctor). The "DIRS"
table of the 8th sector standard isn't made.



    :: File formats

    Texts. QC shows any file of up to 255 sectors as text (up to
64K,  loaded  into  pages 0-3); a packed file is shown unpacked.
There  is no line table (since 3.30; before, it took all of page
7,  5460 lines at most): the viewer finds lines as it goes. Back
it  goes  from  a line start it keeps for each 256-byte block of
the text it has been in (a byte a block, 256 bytes at #BF00, the
overlay  area's end), elsewhere from the start of a "hard" line:
after  an  LF,  or  a  CR  or 0 with no LF after it (so does the
text's  end: a page up from it). On 48K (since 3.22) the text is
shown up to 16383 bytes (until 3.30 up to #2Fxx, 12K). After the
text the viewer puts the end mark #FF (a byte UTF-8 never has).

    Encoding: cp866 or UTF-8. A text with no byte of #80 or more
is cp866 (DOS in the info line). Otherwise QC checks it from the
first  such  byte:  up  to  16  multibyte  sequences within 1024
characters. A sequence starts with #C2..#DF (1 continuation byte
follows),   #E0..#EF   (2),  #F0..#F4  (3);  a  continuation  is
#80..#BF.  The  text  isn't UTF-8 if a byte #80..#C1 or #F5..#FF
starting  a  character, or a cut sequence, comes first. Overlong
forms,  surrogates  and  codes  above U+10FFFF aren't checked. C
reloads the file in the other encoding.

    QC  turns  UTF-8  into  cp866  in place: А..я, Ё, ё to their
cp866  codes;  the pseudographics U+25xx (░▒▓, frames, █▄▌▐▀) to
#B0..#DF;  the  quotes U+00AB, U+00BB, U+201C, U+201D, U+201E to
",  U+2018,  U+2019  to  ';  the dashes U+2013, U+2014 to -; the
ellipsis  to three dots; Є, є to Е, е; Ї, ї and the Ukrainian I,
i (U+0406, U+0456) to Latin I, i; Ў, ў to У, у; the Ukrainian G,
g  (U+0490,  U+0491) to Г, г; a BOM, soft hyphen and stress mark
are  dropped;  the  viewer font's signs (U+2265, U+2264, U+2320,
U+2321,  U+00F7, U+2248, °, U+2022 and ∙, ·, √, №, U+00B2, ■ and
the  no-break  space)  to  its codes #F2..#FF, and ¤ to #FD (the
font's  square,  U+00B2); other characters, all 4-byte ones too,
to  ?. A byte starting no sequence stays as is; but cp866 inside
UTF-8 survives only by chance (cp866's "ра", #E0 #A0, looks like
the start of a 3-byte sequence and becomes ?).

    The  viewer's  font:  256  signs 4 dots wide, 64 columns, 23
text  lines.  #00  blank,  #01-#1F and #7F cp437's signs (faces,
suits,  arrows,  house),  #80-#AF  А..п, #B0-#DF pseudographics,
#E0-#EF  р..я,  #F0  Ё, #F1 ё, #F2-#FF the signs U+2265, U+2264,
U+2320, U+2321, U+00F7, U+2248 (greater or equal, less or equal,
integral  halves,  divide,  almost equal), °, ∙, ·, √, №, U+00B2
(square),  ■ and blank. At #F2-#F7 and #FD the font differs from
cp866 (Є є Ї ї Ў ў and ¤ there).

    A  line  ends with CR (#0D), LF (#0A), CR LF or a 0 byte; LF
CR  gives an extra empty line; there is none after the last line
end.  Tab  (9)  goes to the next column that is a multiple of 8.
Codes 11, 12, 21-31 and #7F print as the font's signs.

    Colours  follow  ACEdit:  codes  1-7 ink 1-7 on black, 8 the
normal  text colour (from the settings), 14-20 bright ink 1-7 on
black  (code  less  13).  A code prints as a space and acts from
where it stands; there is one attribute per two characters, so a
code  in  a  cell's  second half acts from the next cell. A code
right  before  the  line  end  (CR, LF or 0) sets the colour the
whole  line  starts  with;  not  so with CR LF ends (a CR stands
before  the  LF),  and  in a line wrapped by width only its last
part  gets  it. Code 0 sets no colour: it ends the line. M steps
the modes (the start's from TXTMODE bits 2-3): colours; codes as
the  font's  signs,  text  in one colour; codes hidden (spaces),
text in one colour.

    Wrapping  (W): without it lines are cut at column 64; simple
wrapping  is  at  column  64;  "smart"  wrapping  after the last
separator  within  64 columns (space . , ! ? - / \ : ;), else at
column  64  too.  A  line of exactly 64 characters followed by a
line end (or a code) gives no extra empty line.

    ALASM  4.x  sources (since 3.30): a file of up to 16K with a
64-byte header (H at +8, 8 bytes adding up to #80 at +#28), then
the lines, each a length byte (counted too) and its bytes, and 0
at  the  end. In a line: 1..#F that many spaces, #10 the rest of
the  line  as  is,  bytes  from  #80  up  tokens  (the first the
mnemonic,  then  operands),  ";"  a comment to the line's end, a
quote  a  string  to  the  next quote, #FF nothing. QC turns the
source  into  text with ACEdit colour codes, as in an IDE: label
6,  instruction  8  (the  text  colour),  jump  3,  directive 2,
operands  7,  comment  4;  a  code  takes the place of the space
before  its  part.  The  text viewer shows it in cp866; the text
ends at 64K (16K on 48K) or where it would overtake the source's
unread part (4 times the source and more).

    Pictures.  The  length must be exact, its low byte 0 but for
.bsc: 6144 (#1800) pixels only, attributes #07 (white on black);
6912  (#1B00)  a screen; 11136 (#2B80) a screen with its border,
.bsc;  13824 (#3600) a gigascreen, .img, on 128K and more; 49152
(#C000)  an  @-file, its first 6912 bytes shown as a screen. The
length  must  fit  the sectors (see "A file's length" above): an
@-file  has 192 sectors, and on 48K no @-file is shown. Space, A
and  the  left  button step the colours round: its own, black on
white  (#38),  white on black (#07); for 6144 white on black and
black  on  white;  for  .bsc  and a gigascreen only their own. A
packed  picture is known by its unpacked length. The .mlt format
isn't supported.

    .bsc:  6912  bytes of screen and 4224 of border; the picture
is 384x304 (64 pixels left and right, 64 lines above, 48 below),
a colour per 8 pixels of a line, two a byte, in bits 0-2 and 3-5
(bits  6-7  ignored).  QC  draws the border: its picture becomes
code  that puts the colours to port #FE by OUT (C),r as the beam
goes  (colours in A, B, D, E, H, L, loaded ahead). The timing is
told  by the frame length: Pentagon 71680 T-states (ZX-Evolution
in  either  configuration  too;  on  TS-Conf an interrupt missed
under DI waits till taken, so the frame is counted from a second
HALT),  48K  69888,  128K 70908; a +2A/+3 has the same frame but
its  own  timing  (the paper 3 T-states later, no contention for
ports  or  internal T-states), told by the 48K ROM's byte #0B53:
its bit 0 is 0 only on a +2A/+3. A Scorpion has a 48K frame (the
paper at 14344, as in Unreal Speccy and MAME), but its M1 starts
on  an  even  T-state, an instruction of odd T-states taking one
more:  the  frame  count  loop  is  longer,  and  the  code uses
instructions  of  even  T-states  only.  Before  the first frame
probes  set  the interrupt's phase to the T-state; on a Spectrum
the  code  also  gets in step with the ULA by a screen read. The
code  lies  in  the  window,  in  page 0 (#C000), in the pixels'
place;  frames  are  counted  by IM 2 (I = #BE, the table in the
overlay  area).  Strokes  under  3  cells  (24  pixels, OUT's 12
T-states)  and  too  many  colours in a row can't be shown: such
changes  are  dropped,  and then (as with a one-colour border) a
sign  of  two  wavy lines, white on black, goes in the picture's
bottom  right  corner.  Identical  lines in a row are drawn by a
loop  over  one  line's  code  (count in LX): shorter code, made
sooner.  On other machines (and in turbo mode) the border is one
colour,  its  picture's  most  frequent  (on  a  tie  the higher
number). On exit the border is black again.

    .img:  two 6912-byte screens in a row. QC puts the second in
page  7  and every frame, right after the interrupt, flips bit 3
of  #7FFD:  the  screens  alternate,  and  the  eye  mixes their
colours.  This  overwrites  page  7: where the resident is there
(128K,  Scorpion,  Profi,  ATM,  ZX-Evolution: see the code page
above), it is gone after a gigascreen.

    Fonts:  768  bytes  are  96  characters of 8 bytes, top down
(usually  codes  #20-#7F),  shown 32 a row on screen rows 10-12.
2048  bytes  are  256 characters: the file itself is copied into
the  screen's top third (#4000), and the characters are drawn on
rows  16-23.  White  on  black; Enter gives the next file, other
keys exit.

    Sprites  (Symbol  shift  + V): any file as a black and white
picture.  A  pixel  line is the sprite's width in bytes in a row
(the  high  bit  leftmost),  lines  follow  one another, with no
character  cells  or attributes; the screen shows 184 lines. The
width  is 1..32 bytes (32 at first). The info line shows the top
left  byte's file offset, in decimal. A file under 5888 bytes is
padded with zeros.

    Music: Pro Tracker 3 and Vortex Tracker II modules (PT3) and
Pro Tracker 2 modules (PT2), Sergey Bulba's PTSPlay (release 0).
QC looks for a PT3 text header anywhere in the file (so it finds
compiled modules with a player too): a T followed by an r, a P 4
bytes  before  the  r  ("ProTracker")  or  a V 8 bytes before it
("Vortex Tracker"),  and a b #3F bytes from the P or V (" by ").
The  whole  file is searched, by 16K parts; the header may go on
from  one  part into the next (till 3.30 its 64 bytes had to lie
in  one); in files under 256 bytes it isn't looked for (a module
is found by its structure only, below). The header:

        +#00  "ProTracker 3.x compilation of " (the version
              at +#0D) or "Vortex Tracker II 1.0 module: "
        +#1E  title, 32 bytes (line 22, "PT3.5 : ")
        +#3E  " by "
        +#42  author, 32 bytes (line 23, "Author: ")
        +#63  note table (bits 0-1)
        +#64  tempo
        +#65  positions (for the position bar)
        +#66  loop position
        +#67  patterns' pointer
        +#69  32 samples' pointers
        +#A9  16 ornaments' pointers
        +#C9  positions' list, ended by #FF

    The  version  is  the  digit  at  +#0D;  a non-digit (Vortex
Tracker's  r)  counts as 6. Below 4 the old note tables, below 5
the  old  volume  table,  below 6 the old portamento, from 7 Pro
Tracker  3.7's  rule  for commands 1xx and 2xx with delay 0. The
title  and  author  print in QC's font: #20-#AF as they are (#7F
the  copyright  sign), #E0-#EF р..я, #F0-#FF QC's signs, #00-#1F
and #B0-#DF the chequered sign ▒.

    Without a text header a module is looked for by its header's
structure in the file's first 3K (the author's UniSearch, 2005):
tempo  1..#3F,  1 or more positions with the loop position among
them,  the  positions'  list  ended  by  #FF  right  before  the
patterns,  the empty ornament 0 (PT3: 0, 1, 0; PT2: 1, 0, 0). So
PT2  modules  are  found (bare or after Pro Tracker 2's player),
and  PT3  modules without the text. The format on line 22: PT3.x
(the  version from the text), VT II, PT3 (no text) or PT2 (title
only: PT2's header has no author).

    A module plays if the farthest of its 48 sample and ornament
pointers is under #4000 (from the module's start). A module that
doesn't  fit  the window where it lies (going on into the file's
next  16K part) QC gathers at its part's start: copies its piece
there  and the rest from the next part after it (not on 48K: the
next  part isn't in memory there; till 3.30 only a module from a
part's  last  6912  bytes was moved, the others weren't played).
The  tune  ends  at  the  #FF  after  the  positions' list: with
looping,  play  goes  on from the loop position; without, the AY
goes  silent  and  QC  moves  to  the next file. F plays 3 times
faster.  TurboSound on two AYs: Vortex Tracker II pairs (two PT3
modules one after the other at the file's end, then "PT3!" size1
"PT3!"  size2  "02TS";  the first one the module found; the pair
gathered  as  one module, the first alone if it doesn't fit 16K;
till  3.30  only  at  the  file's  start)  and Alone Coder's Pro
Tracker 3.7 TS modules (version 7 and on, byte 98 not a space).

    Hrust  2  (hr2):  the  block  must start at the file's first
byte:

        +0  "hr2"
        +3  flags: bit 7 = 1 the data not packed
        +4  unpacked data's length (a word)
        +6  packed block's length, counted from +8
        +8  packed block

    One block; what follows isn't read. The unpacked data L must
fit  with  room  to spare: L + L/8 + 272 at most 64K, i.e. up to
58012  bytes;  on  48K  up  to 14321 bytes. A file starting with
"hr2" that fails the check isn't tried as ZX0.

    Hrust  1 (since 3.30; Hrumer's DEHRUST format): a block from
the file's first byte too:

        +0  "HR"
        +2  unpacked data's length (a word)
        +4  whole block's length (a word)
        +6  unpacked data's last 6 bytes
        +12 packed stream

    The  block is taken if its length is the file's or up to 255
bytes  less; the data's limits are Hrust 2's. Otherwise the file
is  tried as ZX0. Hrip archives ("HRi" at the start, their first
block's "Hrst2" at +8) aren't unpacked, only coloured.

    ZX0:  format  ZX0 v2, forward (the stream for dzx0_standard;
dzx0_turbo and dzx0_mega share it); backward (-b) and the old v1
(-c)  won't  do.  ZX0  has  no  header,  so QC knows a stream by
itself: it unpacks it on trial, writing nothing, and checks that
each copy is of data already unpacked, the end marker is exactly
at  the  file's  last byte, the data never overtake the stream's
unread  part and stay within 64K. So the file's catalogue length
must be the stream's exact length, not rounded to a sector. Data
up to 64K; on 48K the file up to 16K and the data in page 0 with
256 bytes to spare.

    What  U  writes: the name typed (the packed file's offered),
type  X for p_X or z_X, else C, two spaces in the start field (a
code  file's  load  address  and a BASIC program's length, which
TR-DOS  keeps  in the start, aren't restored), the data's length
and  the  sectors  for  it;  the  file  goes from the first free
sector, its entry to the catalogue's end.


    :: Real Commander's conventions

    QC   keeps  a  few  conventions  of  Real  Commander  (Pawel
Kislyak): CMOS cell #10 is the current drive (QC's input drive);
bit 5 of the settings byte (in CMOS cell #15 and the resident) =
1  means QC's settings, 0 RC's; the way back to the commander is
by  the  signature  LD SP,#??FF (the word #FF31) at #C000 of the
resident's  page.  Real Commander keeps its resident in page #17
and  leaves  to TR-DOS via JP 15649 (#3D21), QC in page #D7 (see
"The resident and the return to QC").


    :: The ZX0 licence

    The  ZX0  depacker  in QC (the loader unpacks QC's code with
it, U and the viewers ZX0 files, and it checks a ZX0 stream too)
is  the  "standard"  one of ZX0 v2 by Einar Saukas and Urusergi.
Its licence:

    BSD 3-Clause License

    Copyright (c) 2021, Einar Saukas
    All rights reserved.

    Redistribution and use in source and binary forms, with or
without modification, are permitted provided that the following
conditions are met:

    1. Redistributions of source code must retain the above
       copyright notice, this list of conditions and the
       following disclaimer.

    2. Redistributions in binary form must reproduce the above
       copyright notice, this list of conditions and the
       following disclaimer in the documentation and/or other
       materials provided with the distribution.

    3. Neither the name of the copyright holder nor the names of
       its contributors may be used to endorse or promote
       products derived from this software without specific
       prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.


                 ░            ░▓▄▄▄▄▄
▄             ▓  ▓▀ ▀▀▀▓▄▄▄▄▄  ▀▓█▄ ▀▀▀████▓▄▄▄▄              ▓
██▓██▄▄▄     ▓░        ░    ▀▀▀▀▒▀█▓▄       ▀▀▀▀██▓██▄▄▄     ▓░
  ░▀▀▀▓███▓▄█▒                  ░  ▒   ▀░         ░▀▀▀▓███▓▄█▒
      ░  ▀▀█ ░                     ░                  ░  ▀▀█ ░