;##############################################################################
; Cheyenne Advanced Systems (CAS) disk interface ROM disassembly
; Version of ROM: 1986
;
; File: CAS-1986-16K-DecodedBin_1.0.asm
; Version: 1.0 - Jun/13/2016
; Character encoding: UTF-8
;
; Disassembled by: TK90X Fan/Conscience (cantinhotk90x@bol.com.br)
; Binary files of ROM provided by: Eduardo Luccas (http://luccas.com.br/)
; Part of this work is based on "Disassembly comentado da ROM" by Jorge Braga
;(http://www.cobit.xpg.com.br/hardware/ids/ids.htm, retrieved at May/05/2016).
;
; Disclaimer: current legal status of Technology Research ROM is unknown, but
;Cheyenne Advanced Systems modification is surely illegal. I have no ownership
;of Beta Disk Interface hardware and software intellectual property nor of 
;the Brazilian clone. This document is only a product of my personal study and
;all data and information is for informational purposes only. I make no
;representations as to accuracy, completeness, currentness, suitability, 
;or validity of any information on this document and shall not be liable for 
;any errors, omissions, or delays in this information or any losses, injuries, 
;or damages arising from its display or use. All information is provided on an 
;as-is basis.
;==============================================================================
; Cheyenne Advanced Systems (CAS) was the first Beta 48 disk interface clone
;produced in Brazil, released in 1986. Unlike later clones released by another
;companies, CAS interface is almost an unmodified copy of the Technology 
;Research product.
;
; CAS disk interface has two ROMs: one is a copy of ZX Spectrum ROM (BASIC ROM)
;and another holds Beta disk operating system (DOS ROM). The BASIC ROM replaces
;TK90X ROM to overcome incompatibility with DOS ROM. The binary file used in
;this work is not a simple dump of DOS ROM. D0 and D7 data lines of this ROM 
;are interchanged in the printed circuit board, thus its raw contents are 
;unsuitable for disassembly. Modified decoded binary file was generated by 
;Eduardo Luccas and disassembled by TK90X Fan/Conscience with z80dasm 1.1.3 
;(https://packages.debian.org/stretch/z80dasm) installed in Debian/GNU Linux 
;distribution  Stretch version (a.k.a. testing version, see 
;https://wiki.debian.org/DebianStretch).
;
; The DOS ROM has only 8192 bytes of size and occupies all 16384 bytes of 
;Spectrum ROM address space (#0000/0-#3FFF/16383). This area is splitted in two
;pages: page 1 located at #0000/0-#1FFF/8191 and the second page at #2000/8192-
;#3FFF/16383. DOS ROM occupies both pages, the contents of which are mirrored. 
;Very few routines are accessed in the first page; almost all of them run in 
;the second page.
;
; The operating system of Beta interface is known as "Beta DOS" in Brazil and 
;as "TRDOS" in another countries. In this document it is called simply "DOS".
;##############################################################################

;##############################################################################
; Disassembly listing - part 1
; First mirrored page of CAS interface ROM (#0000-#1FFF/0-8191).
; This is the entry point for RESET (initialization), RST (restart) and NMI 
;(magic button) routines.
;##############################################################################

    org    #00000

;==============================================================================
; Routine: RST 0 - RESET
; RESET is executed when computer is powered-on or reset button is pressed.
;Maskable interrupt is disabled, BASIC ROM is disabled, DOS ROM is enabled, 
;Beta interface I/O ports are enabled and any I/O operations with peripherals
;attached to Beta rear connector are inhibited. Most of this routine closely 
;resembles ZX Spectrum initialization routine. This code is a bit messy because 
;many bytes must be skipped to avoid colision with restart and NMI routines.
;==============================================================================
RESET                   ;#0000
    ld d,e              ;       Useless instruction, it should be 'di'.
    ld de,65535         ;       Max addressable byte by Z80 CPU (#FFFF).
    ld a,7              ;       Border colour (7=white).
    jr RESET01          ;#0009  Skip next byte.

;------------------------------------------------------------------------------
; Routine: RST 8 - unused
; This restart subroutine is not used by DOS ROM. Any call to this address
;triggers ZX Interface 1 ROM switching, so is avoided by DOS. Another address
;with same effect is #1708 located in the first page of DOS ROM; it is never
;accessed by DOS routines, thus is harmless. 
;------------------------------------------------------------------------------
    nop                 ;#0008  This byte is skipped by RESET.

;------------------------------------------------------------------------------
; RESET01 (#0009/9) is part of RESET routine.
;------------------------------------------------------------------------------
RESET01                 ;#0009
    out (254),a         ;       Define screen border colour.
    ld a,63             ;       I register will be assigned with this value.
    jr RESET02          ;#0013  Skip RST 16 routine.
    nop                 ;       Unused byte.

;==============================================================================
; Routine: RST #10/RST 16 - PRiNt CHaR
; Like BASIC ROM routine counterpart, print character to the current stream. 
;Disk configuration data stored in printer buffer can be saved, depending on 
;the SV_DCFG flag.
; Input:  A=character code;
;         (SV_DCFG)=0 (save config data in printer buffer).
; Called by: DS_CAT, DS_FORMAT, EDITLINE, PRNSTR01, PR_FILENAM, PRNCHR01.
;==============================================================================
PRNCHR                  ;#0010
    jp PRNCHR01         ;#3D21  Jump to the main print character routine.

;------------------------------------------------------------------------------
; RESET02 (#0013/19) is part of RESET routine.
;------------------------------------------------------------------------------
RESET02                 ;#0013
    ld i,a              ;       I=63.
    jp RESET03          ;#201B  Jump to second page of ROM.

;==============================================================================
; Routine: RST #18/RST 24 - PRiNt STRing
; Print sequence of characters until end marker is found. Marker may be 0 
;(which is not printed) or any byte with bit 7 high (which is printed after 
;bit 7 being lowered).
; INPUT:  HL=string start address.
; Called by: DOS_CLI02, FILEENTRY01, ID_TYPE, DS_CAT, DS_FORMAT, RDWRSECT.
;==============================================================================
PRNSTR                  ;#0018
    jp PRNSTR01         ;#377B  Jump to the main print string routine.

;------------------------------------------------------------------------------
; Mirror (#001B/27-#001F/31) of RESET03 (#201B/8219-#201F/8223).
;------------------------------------------------------------------------------
    nop
    nop
    nop
    jr $+6

;==============================================================================
; Routine: RST #20/RST 32 - SAVE HL
; Save HL register pair before a call for BASIC routine.
; Output: (HLTEMP)=HL.
; Called by: DS_MERGE, MKBASROOM, BAS_RMFP, BAS_BCSPC, BAS_NXTCHR, BAS_RECLM,
;BAS_MKROOM, CALLBAS1.
;==============================================================================
SAVE_HL                 ;#0020
    ld (HLTEMP),hl      ; Store content of HL into DOSsystem variable.
    ret                 ; End of subroutine.

;------------------------------------------------------------------------------
; Mirror (#0024/36-#0027/39) of RESET04 (#2024/8228-#2027/8231).
;------------------------------------------------------------------------------
    ld h,d
    ld l,e
    jr $+5

;==============================================================================
; Routine: RST #28/RST 40 - SELect CHannel INFO
; Calculate address of current input/output channel information block plus 
;offset. Used to select a field within channel information block.
; Input:  C=offset value.
; Output: HL=address of current channel with displacement added.
; Called by: INIT_RND, CHBUFFADD, CH_OUT02, GETSEGMT, NEWSEGMT, INPNXTCHR, 
;SEEKNXTSEG, RD_STMFENT, WR_CHBUFF, CURSSECT, STREAMDRV, ENDSTMFL, CHOUT_RND,
;GETRECORD, RNDRECORD, FLUSHCBUF, READMODE, WR_STMFENT.
;==============================================================================
    jp SEL_CHINFO       ;#33B7  Jump to the main subroutine.

;------------------------------------------------------------------------------
; Mirror (#002B/43-#0065/101) of RESET05 routine (#202B/8235-#2065/8293).
;------------------------------------------------------------------------------
    ld (hl),2
    dec hl
    cp h
    jr nz,$-4
    or a
    sbc hl,de
    add hl,de
    inc hl
    jr nc,$+8
    dec (hl)
    jr z,$+5
    dec (hl)
    jr z,$-11
    dec hl
    ld (P_RAMT),hl
    ld de,16047
    ld bc,168
    ld a,e
    ex de,hl
    ld sp,24576
    call LDDR_BAS
    ex de,hl
    inc hl
    ld (UDG),hl
    dec hl
    ld bc,#1E40
    ld (RASP),bc
    ld (RAMTOP),hl
    ld hl,DOS_CLI
    jr $+6
    defb #FF

;==============================================================================
; Routine: NMI - Non-maskable interrupt routine 
; Address: #66/102
; Magic Button press activates /NMI (non-maskable interrupt) signal of Z80 CPU. 
;Maskable interrupt is disabled, BASIC ROM is disabled, DOS ROM is enabled and 
;subroutine at #66/102 is called. This routine saves all contents of computer 
;RAM into a disk file (except first byte of KSTATE and some positions of Z80 
;stack). All registers are saved onto Z80 stack. Afterwards the saved file can 
;be copied, renamed and executed with GOTO statement.
;==============================================================================
NMI                     ;#0066
    jp NMI01            ;#39DA  Main NMI routine resides in the second page.

;------------------------------------------------------------------------------
; Mirror (#0069/105-#1FFF/8191) of #2069/8297-#3FFF/16383 area.
;------------------------------------------------------------------------------
    ld (CHARS),hl       ;0069    22 36 5c     " 6 \ 
    ld hl,(RAMTOP)      ;006c    2a b2 5c     * . \ 
    ld (hl),#3E         ;006f    36 3e     6 > 
    dec hl              ;0071    2b     + 
    ld sp,hl            ;0072    f9     . 
    dec hl              ;0073    2b     + 
    dec hl              ;0074    2b     + 
    ld (ERR_SP),hl      ;0075    22 3d 5c     " = \ 
    ld de,#1303         ;0078    11 03 13     . . . 
    push de             ;007b    d5     . 
    im 1                ;007c    ed 56     . V 
    ld iy,ERR_NR        ;007e    fd 21 3a 5c     . ! : \ 
    ld hl,CHANSCOPY     ;0082    21 b6 5c     ! . \ 
    ld (CHANS),hl       ;0085    22 4f 5c     " O \ 
    ld de,#15AF         ;0088    11 af 15     . . . 
    ld bc,21            ;008b    01 15 00     . . . 
    ex de,hl            ;008e    eb     . 
    call LDIR_BAS       ;008f    cd cf 3c     . . < 
    ex de,hl            ;0092    eb     . 
    dec hl              ;0093    2b     + 
    ld (DATADD),hl      ;0094    22 57 5c     " W \ 
    inc hl              ;0097    23     # 
    ld (PROG),hl        ;0098    22 53 5c     " S \ 
    ld (VARS),hl        ;009b    22 4b 5c     " K \ 
    ld (hl),#80         ;009e    36 80     6 . 
    inc hl              ;00a0    23     # 
    ld (E_LINE),hl      ;00a1    22 59 5c     " Y \ 
    ld (hl),#0D         ;00a4    36 0d     6 . 
    inc hl              ;00a6    23     # 
    ld (hl),#80         ;00a7    36 80     6 . 
    inc hl              ;00a9    23     # 
    ld (WORKSP),hl      ;00aa    22 61 5c     " a \ 
    ld (STKBOT),hl      ;00ad    22 63 5c     " c \ 
    ld (STKEND),hl      ;00b0    22 65 5c     " e \ 
    ld a,%00111000      ;00b3    3e 38     > 8 
    ld (ATTR_P),a       ;00b5    32 8d 5c     2 . \ 
    ld (ATTR_T),a       ;00b8    32 8f 5c     2 . \ 
    ld (BORDCR),a       ;00bb    32 48 5c     2 H \ 
    ld hl,#0523         ;00be    21 23 05     ! # . 
    ld (REPDEL),hl      ;00c1    22 09 5c     " . \ 
    dec (iy-58)         ;00c4    fd 35 c6     . 5 . 
    dec (iy-54)         ;00c7    fd 35 ca     . 5 . 
    ld hl,#15C6         ;00ca    21 c6 15     ! . . 
    ld de,STRMS         ;00cd    11 10 5c     . . \ 
    ld bc,14            ;00d0    01 0e 00     . . . 
    call LDIR_BAS       ;00d3    cd cf 3c     . . < 
    set 1,(iy+1)        ;00d6    fd cb 01 ce     . . . . 
    ld hl,#0EDF         ;00da    21 df 0e     ! . . 
    call CALLBAS        ;00dd    cd 36 2e     . 6 . 
    ld hl,DF_SZ         ;00e0    21 6b 5c     ! k \ 
    ld (hl),2           ;00e3    36 02     6 . 
    ld hl,#128B         ;00e5    21 8b 12     ! . . 
    push hl             ;00e8    e5     . 
    ld a,#AA            ;00e9    3e aa     > . 
    ld (BUFFER),a       ;00eb    32 00 5b     2 . [ 
    jp RESET09          ;00ee    c3 41 3c     . A < 
    call IF1VSWP        ;00f1    cd 8c 31     . . 1 
    call RST_ERRSP      ;00f4    cd d5 21     . . ! 
    call BAS_CLS        ;00f7    cd 33 2e     . 3 . 
    ld hl,(E_LINE)      ;00fa    2a 59 5c     * Y \ 
    inc hl              ;00fd    23     # 
    ld e,(hl)           ;00fe    5e     ^ 
    inc hl              ;00ff    23     # 
    ld d,(hl)           ;0100    56     V 
    ld a,d              ;0101    7a     z 
    or e                ;0102    b3     . 
    ex de,hl            ;0103    eb     . 
    jr z,$+6            ;0104    28 04     ( . 
    xor a               ;0106    af     . 
    ld (LDPKEXEC),a     ;0107    32 10 5d     2 . ] 
    ld (NEWPPC),hl      ;010a    22 42 5c     " B \ 
    xor a               ;010d    af     . 
    ld (NSPPC),a        ;010e    32 44 5c     2 D \ 
    ld hl,#16B0         ;0111    21 b0 16     ! . . 
    call CALLBAS        ;0114    cd 36 2e     . 6 . 
    ld hl,(PROG)        ;0117    2a 53 5c     * S \ 
    dec hl              ;011a    2b     + 
    ld (DATADD),hl      ;011b    22 57 5c     " W \ 
    ld hl,EXEC_BAS02    ;011e    21 21 3c     ! ! < 
    call CALLBAS        ;0121    cd 36 2e     . 6 . 
    call IF1VSWP        ;0124    cd 8c 31     . . 1 
    ld a,#FF            ;0127    3e ff     > . 
    ld (DOSMODE),a      ;0129    32 15 5d     2 . ] 
    xor a               ;012c    af     . 
    ld (ZEROVAR),a      ;012d    32 f7 5c     2 . \ 
    ld a,#AA            ;0130    3e aa     > . 
    ld (FLAGBUFF),a     ;0132    32 17 5d     2 . ] 
    ld hl,BASDOSRET     ;0135    21 a4 21     ! . ! 
    ld (DOS_RET),hl     ;0138    22 1a 5d     " . ] 
    ld hl,0             ;013b    21 00 00     ! . . 
    add hl,sp           ;013e    39     9 
    ld (OLDSP),hl       ;013f    22 1c 5d     " . ] 
    dec hl              ;0142    2b     + 
    dec hl              ;0143    2b     + 
    ld sp,hl            ;0144    f9     . 
    call DEF_ERRSP      ;0145    cd c0 21     . . ! 
    ld hl,(CH_ADD)      ;0148    2a 5d 5c     * ] \ 
    call ENDLINE        ;014b    cd 64 21     . d ! 
    jp z,DSTM_RET       ;014e    ca 70 21     . p ! 
    cp #EA              ;0151    fe ea     . . 
    inc hl              ;0153    23     # 
    jr nz,$-9           ;0154    20 f5       . 
    call ENDLINE        ;0156    cd 64 21     . d ! 
    jr z,$-11           ;0159    28 f3     ( . 
    cp #3A              ;015b    fe 3a     . : 
    jp nz,DSTM_RET      ;015d    c2 70 21     . p ! 
    inc hl              ;0160    23     # 
    jp DOSMAIN          ;0161    c3 96 22     . . " 
    ld a,(hl)           ;0164    7e     ~ 
    cp #0D              ;0165    fe 0d     . . 
    ret z               ;0167    c8     . 
    cp #80              ;0168    fe 80     . . 
    ret z               ;016a    c8     . 
    or a                ;016b    b7     . 
    ret                 ;016c    c9     . 
    call WRT_BUFFER     ;016d    cd f0 2e     . . . 
    ld a,#FF            ;0170    3e ff     > . 
    ld (SV_DCFG),a      ;0172    32 0c 5d     2 . ] 
    call BAS_SETW       ;0175    cd fb 2d     . . - 
    call IF1VSWP        ;0178    cd 8c 31     . . 1 
    ld hl,FLAGBUFF      ;017b    21 17 5d     ! . ] 
    ld a,(hl)           ;017e    7e     ~ 
    or a                ;017f    b7     . 
    ld (hl),#AA         ;0180    36 aa     6 . 
    jr nz,$+5           ;0182    20 03       . 
    call LOADBUFF       ;0184    cd 96 3f     . . ? 
    ld hl,RM_FPC        ;0187    21 1f 5d     ! . ] 
    ld a,(hl)           ;018a    7e     ~ 
    or a                ;018b    b7     . 
    ld (hl),0           ;018c    36 00     6 . 
    jr nz,$+8           ;018e    20 06       . 
    call BAS_RMFP       ;0190    cd b9 2e     . . . 
    call FET_ENTER      ;0193    cd b5 21     . . ! 
    ld sp,(OLDSP)       ;0196    ed 7b 1c 5d     . { . ] 
    ld hl,(DOS_RET)     ;019a    2a 1a 5d     * . ] 
    ld bc,(D_ERRCOD)    ;019d    ed 4b 0f 5d     . K . ] 
    ld b,0              ;01a1    06 00     . . 
    jp (hl)             ;01a3    e9     . 
    call RST_ERRSP      ;01a4    cd d5 21     . . ! 
    bit 7,(iy+0)        ;01a7    fd cb 00 7e     . . . ~ 
    ret nz              ;01ab    c0     . 
    ld de,ROM_BASIC     ;01ac    11 7c 3c     . | < 
    ld sp,(ERR_SP)      ;01af    ed 7b 3d 5c     . { = \ 
    push de             ;01b3    d5     . 
    ret                 ;01b4    c9     . 
    call BAS_GETCHR     ;01b5    cd 26 2e     . & . 
    cp #0D              ;01b8    fe 0d     . . 
    ret z               ;01ba    c8     . 
    call BAS_NXTCHR     ;01bb    cd cb 2e     . . . 
    jr $-9              ;01be    18 f5     . . 
    ld hl,(ERR_SP)      ;01c0    2a 3d 5c     * = \ 
    ld (ERRSPTMP),hl    ;01c3    22 13 5d     " . ] 
    ld hl,(OLDSP)       ;01c6    2a 1c 5d     * . ] 
    dec hl              ;01c9    2b     + 
    dec hl              ;01ca    2b     + 
    ld (ERR_SP),hl      ;01cb    22 3d 5c     " = \ 
    ld de,DOSERROR      ;01ce    11 15 3c     . . < 
    ld (hl),e           ;01d1    73     s 
    inc hl              ;01d2    23     # 
    ld (hl),d           ;01d3    72     r 
    ret                 ;01d4    c9     . 
    ld hl,(ERRSPTMP)    ;01d5    2a 13 5d     * . ] 
    ld (ERR_SP),hl      ;01d8    22 3d 5c     " = \ 
    ret                 ;01db    c9     . 
    ld hl,0             ;01dc    21 00 00     ! . . 
    ld (ZEROVAR),hl     ;01df    22 f7 5c     " . \ 
    add hl,sp           ;01e2    39     9 
    ld (OLDSP),hl       ;01e3    22 1c 5d     " . ] 
    dec hl              ;01e6    2b     + 
    dec hl              ;01e7    2b     + 
    ld sp,hl            ;01e8    f9     . 
    call DEF_ERRSP      ;01e9    cd c0 21     . . ! 
    ld hl,FLAGBUFF      ;01ec    21 17 5d     ! . ] 
    ld a,(hl)           ;01ef    7e     ~ 
    cp #AA              ;01f0    fe aa     . . 
    ld a,0              ;01f2    3e 00     > . 
    ld (D_ERRCOD),a     ;01f4    32 0f 5d     2 . ] 
    jp z,DOS_CLI03      ;01f7    ca 5d 22     . ] " 
    ld (hl),#AA         ;01fa    36 aa     6 . 
    call BAS_CLS        ;01fc    cd 33 2e     . 3 . 
    call OPEN_S         ;01ff    cd 22 2e     . " . 
    ld hl,M_LOGO        ;0202    21 ea 22     ! . " 
    rst 24              ;0205    df     . 
    ld a,(BUFFER)       ;0206    3a 00 5b     : . [ 
    cp #AA              ;0209    fe aa     . . 
    jr nz,$+82          ;020b    20 50       P 
    ld hl,(E_LINE)      ;020d    2a 59 5c     * Y \ 
    ld a,254            ;0210    3e fe     > . 
    ld (CLR_WSP),a      ;0212    32 0e 5d     2 . ] 
    ld (hl),#F7         ;0215    36 f7     6 . 
    inc hl              ;0217    23     # 
    ld (hl),#22         ;0218    36 22     6 " 
    inc hl              ;021a    23     # 
    ld (hl),#62         ;021b    36 62     6 b 
    inc hl              ;021d    23     # 
    ld (hl),#6F         ;021e    36 6f     6 o 
    inc hl              ;0220    23     # 
    ld (hl),#6F         ;0221    36 6f     6 o 
    inc hl              ;0223    23     # 
    ld (hl),#74         ;0224    36 74     6 t 
    inc hl              ;0226    23     # 
    ld (hl),#22         ;0227    36 22     6 " 
    inc hl              ;0229    23     # 
    ld (K_CUR),hl       ;022a    22 5b 5c     " [ \ 
    ld (hl),#0D         ;022d    36 0d     6 . 
    inc hl              ;022f    23     # 
    ld (hl),#80         ;0230    36 80     6 . 
    inc hl              ;0232    23     # 
    ld (WORKSP),hl      ;0233    22 61 5c     " a \ 
    ld (STKBOT),hl      ;0236    22 63 5c     " c \ 
    ld (STKEND),hl      ;0239    22 65 5c     " e \ 
    set 3,(iy+1)        ;023c    fd cb 01 de     . . . . 
    jr $+62             ;0240    18 3c     . < 
    ld b,3              ;0242    06 03     . . 
    ld a,(hl)           ;0244    7e     ~ 
    ld (de),a           ;0245    12     . 
    inc hl              ;0246    23     # 
    inc de              ;0247    13     . 
    djnz $-4            ;0248    10 fa     . . 
    ret                 ;024a    c9     . 
    ld b,32             ;024b    06 20     .   
    push bc             ;024d    c5     . 
    xor %00001000       ;024e    ee 08     . . 
    out (255),a         ;0250    d3 ff     . . 
    push af             ;0252    f5     . 
    ld a,5              ;0253    3e 05     > . 
    call DELAY01        ;0255    cd a8 3d     . . = 
    pop af              ;0258    f1     . 
    pop bc              ;0259    c1     . 
    djnz $-13           ;025a    10 f1     . . 
    ret                 ;025c    c9     . 
    ld hl,(OLDSP)       ;025d    2a 1c 5d     * . ] 
    dec hl              ;0260    2b     + 
    dec hl              ;0261    2b     + 
    ld sp,hl            ;0262    f9     . 
    call IF1VSWP        ;0263    cd 8c 31     . . 1 
    call OPEN_K         ;0266    cd 1c 2e     . . . 
    ld a,(PORT255)      ;0269    3a 16 5d     : . ] 
    or 3                ;026c    f6 03     . . 
    call FLIPHLT        ;026e    cd 4b 22     . K " 
    ld a,(PORT255)      ;0271    3a 16 5d     : . ] 
    call FLIPHLT        ;0274    cd 4b 22     . K " 
    xor a               ;0277    af     . 
    ld (DOSMODE),a      ;0278    32 15 5d     2 . ] 
    call EDITLINE       ;027b    cd c6 31     . . 1 
    call BAS_CLSLOW     ;027e    cd 40 2e     . @ . 
    ld hl,DOS_CLI03     ;0281    21 5d 22     ! ] " 
    ld (DOS_RET),hl     ;0284    22 1a 5d     " . ] 
    xor a               ;0287    af     . 
    ld (D_ERRCOD),a     ;0288    32 0f 5d     2 . ] 
    ld hl,(E_LINE)      ;028b    2a 59 5c     * Y \ 
    push hl             ;028e    e5     . 
    ld de,ELINE_T       ;028f    11 20 5d     .   ] 
    call COPY3B         ;0292    cd 42 22     . B " 
    pop hl              ;0295    e1     . 
    ld (DSTMADDR),hl    ;0296    22 11 5d     " . ] 
    ld a,(hl)           ;0299    7e     ~ 
    ld b,a              ;029a    47     G 
    and #80             ;029b    e6 80     . . 
    ld a,b              ;029d    78     x 
    jr z,$+11           ;029e    28 09     ( . 
    cp 254              ;02a0    fe fe     . . 
    jr z,$+7            ;02a2    28 05     ( . 
    push af             ;02a4    f5     . 
    call SEL_DRIVE      ;02a5    cd 71 3d     . q = 
    pop af              ;02a8    f1     . 
    ld hl,T_DSTMCOD     ;02a9    21 c5 3f     ! . ? 
    dec hl              ;02ac    2b     + 
    ld c,0              ;02ad    0e 00     . . 
    inc c               ;02af    0c     . 
    ld d,a              ;02b0    57     W 
    ld a,#13            ;02b1    3e 13     > . 
    cp c                ;02b3    b9     . 
    jp c,DSTM_RET       ;02b4    da 70 21     . p ! 
    ld a,d              ;02b7    7a     z 
    inc hl              ;02b8    23     # 
    cp (hl)             ;02b9    be     . 
    jr nz,$-11          ;02ba    20 f3       . 
    ld a,9              ;02bc    3e 09     > . 
    ld (CMP_SIZE),a     ;02be    32 06 5d     2 . ] 
    xor a               ;02c1    af     . 
    ld (D_ERRCOD),a     ;02c2    32 0f 5d     2 . ] 
    ld (CODEARG),a      ;02c5    32 d6 5c     2 . \ 
    ld (LDPKEXEC),a     ;02c8    32 10 5d     2 . ] 
    ld hl,FLAGS         ;02cb    21 3b 5c     ! ; \ 
    res 7,(hl)          ;02ce    cb be     . . 
    ld b,0              ;02d0    06 00     . . 
    ld hl,T_DSTMADD     ;02d2    21 d8 3f     ! . ? 
    dec c               ;02d5    0d     . 
    sla c               ;02d6    cb 21     . ! 
    add hl,bc           ;02d8    09     . 
    ld e,(hl)           ;02d9    5e     ^ 
    inc hl              ;02da    23     # 
    ld d,(hl)           ;02db    56     V 
    ex de,hl            ;02dc    eb     . 
    push hl             ;02dd    e5     . 
    ld de,STXCH_RET     ;02de    11 e3 22     . . " 
    push de             ;02e1    d5     . 
    jp (hl)             ;02e2    e9     . 
    ld hl,FLAGS         ;02e3    21 3b 5c     ! ; \ 
    set 7,(hl)          ;02e6    cb fe     . . 
    pop hl              ;02e8    e1     . 
    jp (hl)             ;02e9    e9     . 

;------------------------------------------------------------------------------
; Mirror (#02EA/746) of M_LOGO (#22EA/8938) message.
;------------------------------------------------------------------------------
    defb #16,#01,#05    ;       'AT 1,5;'.
    defm "*"
    defm "       "      ;       7 spaces.
    defm "DOS"
    defm "       "      ;       7 spaces.
    defm "*"
    defb #0D,#0D        ;       'Enter', 'Enter'.
    defm "       "      ;       7 spaces.
    defm "cas ltd. "
    defb #7F            ;       'Copyright'.
    defm " 198"
    defb #B6            ;       "6"+#80 (end marker).
;------------------------------------------------------------------------------
; Unused message. Probably remaining of original Beta message.
;------------------------------------------------------------------------------
    defm "         "    ;       9 spaces.
    defb #16,#05,#0B    ;       'AT 5,11;'
    defm "      "       ;       6 spaces.
    defb #00            ;       End marker.
;------------------------------------------------------------------------------

    call READ_CS        ;032b    cd 7f 23     . © # 
    call PRT_ENTER      ;032e    cd 1f 3d     . . = 
    call PRT_ENTER      ;0331    cd 1f 3d     . . = 
    ld bc,(#5BE5)       ;0334    ed 4b e5 5b     . K . [ 
    call BAS_PRNTBC     ;0338    cd 45 2e     . E . 
    ld hl,M_FREE        ;033b    21 77 39     ! w 9 
    rst 24              ;033e    df     . 
    jp DSTM_RET         ;033f    c3 70 21     . p ! 
    push af             ;0342    f5     . 
    ld a,(CLR_WSP)      ;0343    3a 0e 5d     : . ] 
    cp 254              ;0346    fe fe     . . 
    jr nz,$+4           ;0348    20 02       . 
    pop af              ;034a    f1     . 
    ret                 ;034b    c9     . 
    pop af              ;034c    f1     . 
    ld (D_ERRCOD),a     ;034d    32 0f 5d     2 . ] 
    ld a,(DOSMODE)      ;0350    3a 15 5d     : . ] 
    or a                ;0353    b7     . 
    call z,PRNSTR01     ;0354    cc 7b 37     . { 7 
    ret                 ;0357    c9     . 
    ld hl,M_NOFILE      ;0358    21 cd 39     ! . 9 
    ld a,1              ;035b    3e 01     > . 
    jp DSTM_ERRET       ;035d    c3 e5 2c     . . , 
    xor a               ;0360    af     . 
    ld (TRK0SECT),a     ;0361    32 cc 5c     2 . \ 
    ld de,(TRK0SECT)    ;0364    ed 5b cc 5c     . [ . \ 
    ld d,0              ;0368    16 00     . . 
    ld hl,FLAGBUFF      ;036a    21 17 5d     ! . ] 
    xor a               ;036d    af     . 
    cp (hl)             ;036e    be     . 
    ld (hl),a           ;036f    77     w 
    jr z,$+7            ;0370    28 05     ( . 
    push de             ;0372    d5     . 
    call SAVEBUFF       ;0373    cd 9e 3f     . . ? 
    pop de              ;0376    d1     . 
    ld hl,BUFFER        ;0377    21 00 5b     ! . [ 
    ld b,1              ;037a    06 01     . . 
    jp RDSECTORS        ;037c    c3 ea 2e     . . . 
    ld de,8             ;037f    11 08 00     . . . 
    jr $-24             ;0382    18 e6     . . 
    call READ_CS        ;0384    cd 7f 23     . © # 
    ld a,(#5BE7)        ;0387    3a e7 5b     : . [ 
    cp 16               ;038a    fe 10     . . 
    jr z,$+8            ;038c    28 06     ( . 
    ld hl,M_DSKERR      ;038e    21 87 39     ! . 9 
    rst 24              ;0391    df     . 
    jr $-83             ;0392    18 ab     . . 
    call FT_DSKTYPE     ;0394    cd ba 3d     . . = 
    res 0,(hl)          ;0397    cb 86     . . 
    res 1,(hl)          ;0399    cb 8e     . . 
    ld a,(#5BE3)        ;039b    3a e3 5b     : . [ 
    bit 0,a             ;039e    cb 47     . G 
    jr nz,$+4           ;03a0    20 02       . 
    set 0,(hl)          ;03a2    cb c6     . . 
    bit 3,a             ;03a4    cb 5f     . _ 
    ret nz              ;03a6    c0     . 
    set 1,(hl)          ;03a7    cb ce     . . 
    ret                 ;03a9    c9     . 
    ld hl,(DSTMADDR)    ;03aa    2a 11 5d     * . ] 
    inc hl              ;03ad    23     # 
    ld a,(hl)           ;03ae    7e     ~ 
    cp #0D              ;03af    fe 0d     . . 
    ret                 ;03b1    c9     . 
    call NOARG          ;03b2    cd aa 23     . . # 
    ld bc,2             ;03b5    01 02 00     . . . 
    ld (VAR_C_L),bc     ;03b8    ed 43 db 5c     . C . \ 
    jr z,$+45           ;03bc    28 2b     ( + 
    cp #23              ;03be    fe 23     . # 
    jr nz,$+28          ;03c0    20 1a       . 
    ld (CH_ADD),hl      ;03c2    22 5d 5c     " ] \ 
    call GETARG_I       ;03c5    cd a8 2e     . . . 
    call BAS_GETCHR     ;03c8    cd 26 2e     . & . 
    cp #0D              ;03cb    fe 0d     . . 
    jr z,$+28           ;03cd    28 1a     ( . 
    cp #2C              ;03cf    fe 2c     . , 
    jp nz,ER_SYNTX      ;03d1    c2 b3 2d     . . - 
    call BAS_NXTCHR     ;03d4    cd cb 2e     . . . 
    call BAS_EEXP       ;03d7    cd 58 2e     . X . 
    jr $+5              ;03da    18 03     . . 
    call GET1ARG_S      ;03dc    cd 7c 2e     . | . 
    call SYN_CHCK       ;03df    cd 0e 2e     . . . 
    call BAS_STKFET     ;03e2    cd 4e 2e     . N . 
    ex de,hl            ;03e5    eb     . 
    call GET_DRV        ;03e6    cd 1a 2d     . . - 
    call SYN_CHCK       ;03e9    cd 0e 2e     . . . 
    xor a               ;03ec    af     . 
    ld (SV_DCFG),a      ;03ed    32 0c 5d     2 . ] 
    call ID_TYPE        ;03f0    cd 84 23     . . # 
    ld a,(VAR_C_L)      ;03f3    3a db 5c     : . \ 
    cp 2                ;03f6    fe 02     . . 
    push af             ;03f8    f5     . 
    call z,BAS_CLS      ;03f9    cc 33 2e     . 3 . 
    pop af              ;03fc    f1     . 
    cp 17               ;03fd    fe 11     . . 
    jp nc,ER_SYNTX      ;03ff    d2 b3 2d     . . - 
    call BAS_OPEN       ;0402    cd 1d 2e     . . . 
    ld hl,M_TITLE       ;0405    21 9c 39     ! . 9 
    rst 24              ;0408    df     . 
    ld hl,#5BF5         ;0409    21 f5 5b     ! . [ 
    rst 24              ;040c    df     . 
    call PRT_ENTER      ;040d    cd 1f 3d     . . = 
    ld a,(#5BE4)        ;0410    3a e4 5b     : . [ 
    ld hl,#5BF4         ;0413    21 f4 5b     ! . [ 
    sub (hl)            ;0416    96     . 
    push hl             ;0417    e5     . 
    call PRINTN_A       ;0418    cd 0c 39     . . 9 
    ld hl,M_FILE        ;041b    21 d0 39     ! . 9 
    rst 24              ;041e    df     . 
    pop hl              ;041f    e1     . 
    ld c,(hl)           ;0420    4e     N 
    call PRINTN_C       ;0421    cd 0d 39     . . 9 
    ld hl,M_DELFILE     ;0424    21 c2 39     ! . 9 
    rst 24              ;0427    df     . 
    call READT0S0       ;0428    cd 60 23     . ` # 
    ld hl,BUFFER        ;042b    21 00 5b     ! . [ 
    call FILEENTRY      ;042e    cd 86 3f     . . ? 
    call PRT_ENTER      ;0431    cd 1f 3d     . . = 
    ld a,(CURRDRIVE)    ;0434    3a f6 5c     : . \ 
    add a,#41           ;0437    c6 41     . A 
    rst 16              ;0439    d7     . 
    ld b,2              ;043a    06 02     . . 
    call FILEENTRY      ;043c    cd 86 3f     . . ? 
    push bc             ;043f    c5     . 
    ld a,#3A            ;0440    3e 3a     > : 
    rst 16              ;0442    d7     . 
    push hl             ;0443    e5     . 
    call PR_FILENAM     ;0444    cd fa 38     . . 8 
    ld bc,13            ;0447    01 0d 00     . . . 
    pop hl              ;044a    e1     . 
    push hl             ;044b    e5     . 
    add hl,bc           ;044c    09     . 
    ld c,(hl)           ;044d    4e     N 
    push bc             ;044e    c5     . 
    ld a,c              ;044f    79     y 
    ld b,2              ;0450    06 02     . . 
    cp 10               ;0452    fe 0a     . . 
    jr c,$+3            ;0454    38 01     8 . 
    dec b               ;0456    05     . 
    cp #64              ;0457    fe 64     . d 
    jr nc,$+7           ;0459    30 05     0 . 
    ld a,32             ;045b    3e 20     >   
    rst 16              ;045d    d7     . 
    djnz $-3            ;045e    10 fb     . . 
    pop bc              ;0460    c1     . 
    call BAS_PRNTBC     ;0461    cd 45 2e     . E . 
    pop hl              ;0464    e1     . 
    pop bc              ;0465    c1     . 
    ld de,16            ;0466    11 10 00     . . . 
    add hl,de           ;0469    19     . 
    djnz $-46           ;046a    10 d0     . . 
    jr $-62             ;046c    18 c0     . . 
    ld de,16            ;046e    11 10 00     . . . 
    add hl,de           ;0471    19     . 
    ret                 ;0472    c9     . 
    push hl             ;0473    e5     . 
    push bc             ;0474    c5     . 
    ld bc,#A400         ;0475    01 00 a4     . . . 
    add hl,bc           ;0478    09     . 
    jr c,$+5            ;0479    38 03     8 . 
    pop bc              ;047b    c1     . 
    pop hl              ;047c    e1     . 
    ret                 ;047d    c9     . 
    ld hl,TRK0SECT      ;047e    21 cc 5c     ! . \ 
    inc (hl)            ;0481    34     4 
    call READT0SX       ;0482    cd 64 23     . d # 
    pop bc              ;0485    c1     . 
    pop hl              ;0486    e1     . 
    ld hl,BUFFER        ;0487    21 00 5b     ! . [ 
    ret                 ;048a    c9     . 
    and #DF             ;048b    e6 df     . . 
    sbc a,#41           ;048d    de 41     . A 
    jp c,ER_SYNTX       ;048f    da b3 2d     . . - 
    cp 4                ;0492    fe 04     . . 
    jp nc,ER_SYNTX      ;0494    d2 b3 2d     . . - 
    ret                 ;0497    c9     . 
    call BAS_STKFET     ;0498    cd 4e 2e     . N . 
    ld a,c              ;049b    79     y 
    cp b                ;049c    b8     . 
    jp z,ER_SYNTX       ;049d    ca b3 2d     . . - 
    ret                 ;04a0    c9     . 
    call GET1ARG_S      ;04a1    cd 7c 2e     . | . 
    call SYN_CHCK       ;04a4    cd 0e 2e     . . . 
    call USTK_STR       ;04a7    cd 98 24     . . $ 
    ld a,(de)           ;04aa    1a     . 
    call DRIVENUM       ;04ab    cd 8b 24     . . $ 
    ld (DEFLTDRV),a     ;04ae    32 19 5d     2 . ] 
    call SEL_DRIVE01    ;04b1    cd 74 3d     . t = 
    jp DSTM_RET         ;04b4    c3 70 21     . p ! 
    call GET2ARG_S      ;04b7    cd 6a 2e     . j . 
    call SYN_CHCK       ;04ba    cd 0e 2e     . . . 
    call FIND_FTYPE     ;04bd    cd f1 24     . . $ 
    call SEEKFILE       ;04c0    cd 49 2d     . I - 
    ld a,(CURRDRIVE)    ;04c3    3a f6 5c     : . \ 
    ld (SRCDRIVE),a     ;04c6    32 f8 5c     2 . \ 
    jp nz,ER_NOFILE     ;04c9    c2 58 23     . X # 
    push bc             ;04cc    c5     . 
    call GETENTRY       ;04cd    cd ae 27     . . ' 
    call SEEKFILE       ;04d0    cd 49 2d     . I - 
    push af             ;04d3    f5     . 
    ld a,(SRCDRIVE)     ;04d4    3a f8 5c     : . \ 
    ld hl,CURRDRIVE     ;04d7    21 f6 5c     ! . \ 
    cp (hl)             ;04da    be     . 
    jp nz,ER_SYNTX      ;04db    c2 b3 2d     . . - 
    call ID_TYPE        ;04de    cd 84 23     . . # 
    pop af              ;04e1    f1     . 
    jp z,ER_F_EXIST     ;04e2    ca eb 2c     . . , 
    pop bc              ;04e5    c1     . 
    call PUTENTRY       ;04e6    cd bc 27     . . ' 
    jp DIR_RET01        ;04e9    c3 6d 21     . m ! 
    ld a,(LDPKEXEC)     ;04ec    3a 10 5d     : . ] 
    or a                ;04ef    b7     . 
    ret                 ;04f0    c9     . 
    ld b,#43            ;04f1    06 43     . C 
    ld a,(CODEARG)      ;04f3    3a d6 5c     : . \ 
    or a                ;04f6    b7     . 
    jr nz,$+25          ;04f7    20 17       . 
    call BAS_GETCHR     ;04f9    cd 26 2e     . & . 
    cp #AF              ;04fc    fe af     . . 
    ld b,#43            ;04fe    06 43     . C 
    jr z,$+16           ;0500    28 0e     ( . 
    cp #E4              ;0502    fe e4     . . 
    ld b,#44            ;0504    06 44     . D 
    jr z,$+10           ;0506    28 08     ( . 
    cp #23              ;0508    fe 23     . # 
    ld b,#23            ;050a    06 23     . # 
    jr z,$+4            ;050c    28 02     ( . 
    ld b,#42            ;050e    06 42     . B 
    ld hl,FILETYPE      ;0510    21 e5 5c     ! . \ 
    ld (hl),b           ;0513    70     p 
    ret                 ;0514    c9     . 
    push hl             ;0515    e5     . 
    push bc             ;0516    c5     . 
    push de             ;0517    d5     . 
    ld hl,WAITKEY       ;0518    21 a5 3c     ! . < 
    call CALLBAS        ;051b    cd 36 2e     . 6 . 
    ld a,(LASTK)        ;051e    3a 08 5c     : . \ 
    pop de              ;0521    d1     . 
    pop bc              ;0522    c1     . 
    pop hl              ;0523    e1     . 
    and #DF             ;0524    e6 df     . . 
    ret                 ;0526    c9     . 
    ld a,(NOFILE)       ;0527    3a 07 5d     : . ] 
    or a                ;052a    b7     . 
    jp z,ER_NOFILE      ;052b    ca 58 23     . X # 
    jp DSTM_RET         ;052e    c3 70 21     . p ! 
    push bc             ;0531    c5     . 
    ld a,#FF            ;0532    3e ff     > . 
    ld (SV_DCFG),a      ;0534    32 0c 5d     2 . ] 
    call BAS_CLS        ;0537    cd 33 2e     . 3 . 
    ld a,(CURRDRIVE)    ;053a    3a f6 5c     : . \ 
    add a,#41           ;053d    c6 41     . A 
    call PRNCHR01       ;053f    cd 21 3d     . ! = 
    ld a,#3A            ;0542    3e 3a     > : 
    call PRNCHR01       ;0544    cd 21 3d     . ! = 
    ld hl,FILENAME      ;0547    21 dd 5c     ! . \ 
    call PR_FILENAM     ;054a    cd fa 38     . . 8 
    ld hl,M_F_EXST      ;054d    21 f3 37     ! . 7 
    call PRNSTR01       ;0550    cd 7b 37     . { 7 
    call READKEY        ;0553    cd 15 25     . . % 
    cp #59              ;0556    fe 59     . Y 
    push af             ;0558    f5     . 
    call BAS_CLS        ;0559    cd 33 2e     . 3 . 
    pop af              ;055c    f1     . 
    pop bc              ;055d    c1     . 
    ret nz              ;055e    c0     . 
    push bc             ;055f    c5     . 
    call BAS_CLS        ;0560    cd 33 2e     . 3 . 
    pop bc              ;0563    c1     . 
    call ERASENFILE     ;0564    cd 25 27     . % ' 
    xor a               ;0567    af     . 
    ret                 ;0568    c9     . 
    ld a,(FILETYPE)     ;0569    3a e5 5c     : . \ 
    cp #23              ;056c    fe 23     . # 
    jr z,$+4            ;056e    28 02     ( . 
    xor a               ;0570    af     . 
    ret                 ;0571    c9     . 
    ld a,10             ;0572    3e 0a     > . 
    ld (CMP_SIZE),a     ;0574    32 06 5d     2 . ] 
    call SEEKFILE01     ;0577    cd 4c 2d     . L - 
    ld a,9              ;057a    3e 09     > . 
    ld (CMP_SIZE),a     ;057c    32 06 5d     2 . ] 
    ret                 ;057f    c9     . 
    ld a,(FILENAME)     ;0580    3a dd 5c     : . \ 
    cp #2A              ;0583    fe 2a     . * 
    jp nz,ER_NOFILE     ;0585    c2 58 23     . X # 
    call BAS_STKFET     ;0588    cd 4e 2e     . N . 
    ex de,hl            ;058b    eb     . 
    call GET_DRV        ;058c    cd 1a 2d     . . - 
    ld a,(hl)           ;058f    7e     ~ 
    cp #2A              ;0590    fe 2a     . * 
    jp nz,ER_SYNTX      ;0592    c2 b3 2d     . . - 
    ld a,(CURRDRIVE)    ;0595    3a f6 5c     : . \ 
    ld (DESTDRIVE),a    ;0598    32 f9 5c     2 . \ 
    ld a,(DESTDRIVE)    ;059b    3a f9 5c     : . \ 
    call SEL_DRIVE01    ;059e    cd 74 3d     . t = 
    call ID_TYPE        ;05a1    cd 84 23     . . # 
    ld a,#FF            ;05a4    3e ff     > . 
    ld (SRC_ENTR),a     ;05a6    32 0d 5d     2 . ] 
    ld a,(SRCDRIVE)     ;05a9    3a f8 5c     : . \ 
    call SEL_DRIVE01    ;05ac    cd 74 3d     . t = 
    call ID_TYPE        ;05af    cd 84 23     . . # 
    ld a,(SRC_ENTR)     ;05b2    3a 0d 5d     : . ] 
    inc a               ;05b5    3c     < 
    ld (SRC_ENTR),a     ;05b6    32 0d 5d     2 . ] 
    ld c,a              ;05b9    4f     O 
    call GETENTRY       ;05ba    cd ae 27     . . ' 
    ld a,(FILENAME)     ;05bd    3a dd 5c     : . \ 
    cp 0                ;05c0    fe 00     . . 
    jp z,DSTM_RET       ;05c2    ca 70 21     . p ! 
    cp 1                ;05c5    fe 01     . . 
    jr z,$-30           ;05c7    28 e0     ( . 
    ld hl,FILEPARM1     ;05c9    21 e6 5c     ! . \ 
    ld de,FILETEMP      ;05cc    11 ed 5c     . . \ 
    ld bc,7             ;05cf    01 07 00     . . . 
    ldir                ;05d2    ed b0     . . 
    ld a,(DESTDRIVE)    ;05d4    3a f9 5c     : . \ 
    call SEL_DRIVE01    ;05d7    cd 74 3d     . t = 
    call SEEKFILE01     ;05da    cd 4c 2d     . L - 
    jr nz,$+12          ;05dd    20 0a       . 
    call SEEK_STRF      ;05df    cd 69 25     . i % 
    jr nz,$+7           ;05e2    20 05       . 
    call OVERWRITE      ;05e4    cd 31 25     . 1 % 
    jr nz,$-62          ;05e7    20 c0       . 
    call COPYFILE       ;05e9    cd f1 25     . . % 
    call WRT_BUFFER     ;05ec    cd f0 2e     . . . 
    jr $-70             ;05ef    18 b8     . . 
    call READ_CS        ;05f1    cd 7f 23     . © # 
    ld a,(#5BE4)        ;05f4    3a e4 5b     : . [ 
    cp #80              ;05f7    fe 80     . . 
    jp z,ER_NOSPACE     ;05f9    ca e0 2c     . . , 
    ld hl,FILETEMP      ;05fc    21 ed 5c     ! . \ 
    ld de,FILEPARM1     ;05ff    11 e6 5c     . . \ 
    ld bc,7             ;0602    01 07 00     . . . 
    ldir                ;0605    ed b0     . . 
    ld de,(FILESIZE)    ;0607    ed 5b ea 5c     . [ . \ 
    ld d,0              ;060b    16 00     . . 
    or a                ;060d    b7     . 
    ld hl,(#5BE5)       ;060e    2a e5 5b     * . [ 
    sbc hl,de           ;0611    ed 52     . R 
    jp c,ER_NOSPACE     ;0613    da e0 2c     . . , 
    ld (#5BE5),hl       ;0616    22 e5 5b     " . [ 
    ld hl,(#5BE1)       ;0619    2a e1 5b     * . [ 
    ld (FILESECT),hl    ;061c    22 eb 5c     " . \ 
    push hl             ;061f    e5     . 
    call COPYCHUNK      ;0620    cd d3 26     . . & 
    pop hl              ;0623    e1     . 
    ld (FILESECT),hl    ;0624    22 eb 5c     " . \ 
    ld hl,(RWSECID)     ;0627    2a f4 5c     * . \ 
    ld (#5BE1),hl       ;062a    22 e1 5b     " . [ 
    ld hl,#5BE4         ;062d    21 e4 5b     ! . [ 
    inc (hl)            ;0630    34     4 
    ld c,(hl)           ;0631    4e     N 
    dec c               ;0632    0d     . 
    ld b,0              ;0633    06 00     . . 
    push bc             ;0635    c5     . 
    ld de,9             ;0636    11 09 00     . . . 
    ld (RWSECID),de     ;0639    ed 53 f4 5c     . S . \ 
    call WRT_BUFFER     ;063d    cd f0 2e     . . . 
    pop bc              ;0640    c1     . 
    call PUTENTRY       ;0641    cd bc 27     . . ' 
    ret                 ;0644    c9     . 
    call GET2ARG_S      ;0645    cd 6a 2e     . j . 
    call SYN_CHCK       ;0648    cd 0e 2e     . . . 
    call WKSPMEM        ;064b    cd c0 27     . . ' 
    call FIND_FTYPE     ;064e    cd f1 24     . . $ 
    call SEEKFILE       ;0651    cd 49 2d     . I - 
    ld a,(CURRDRIVE)    ;0654    3a f6 5c     : . \ 
    ld (SRCDRIVE),a     ;0657    32 f8 5c     2 . \ 
    jp nz,COPYALL       ;065a    c2 80 25     . . % 
    call GETENTRY       ;065d    cd ae 27     . . ' 
    ld hl,FILEPARM1     ;0660    21 e6 5c     ! . \ 
    ld de,FILETEMP      ;0663    11 ed 5c     . . \ 
    ld bc,7             ;0666    01 07 00     . . . 
    ldir                ;0669    ed b0     . . 
    call SEEKFILE       ;066b    cd 49 2d     . I - 
    push af             ;066e    f5     . 
    push bc             ;066f    c5     . 
    ld a,(CURRDRIVE)    ;0670    3a f6 5c     : . \ 
    ld (DESTDRIVE),a    ;0673    32 f9 5c     2 . \ 
    ld a,(SRCDRIVE)     ;0676    3a f8 5c     : . \ 
    call SEL_DRIVE01    ;0679    cd 74 3d     . t = 
    call ID_TYPE        ;067c    cd 84 23     . . # 
    ld a,(DESTDRIVE)    ;067f    3a f9 5c     : . \ 
    call SEL_DRIVE01    ;0682    cd 74 3d     . t = 
    call ID_TYPE        ;0685    cd 84 23     . . # 
    pop bc              ;0688    c1     . 
    pop af              ;0689    f1     . 
    jr nz,$+13          ;068a    20 0b       . 
    call SEEK_STRF      ;068c    cd 69 25     . i % 
    jr nz,$+8           ;068f    20 06       . 
    call OVERWRITE      ;0691    cd 31 25     . 1 % 
    jp nz,DSTM_RET      ;0694    c2 70 21     . p ! 
    call COPYFILE       ;0697    cd f1 25     . . % 
    call WRT_BUFFER     ;069a    cd f0 2e     . . . 
    ld a,(FILETYPE)     ;069d    3a e5 5c     : . \ 
    cp #23              ;06a0    fe 23     . # 
    jp nz,DSTM_RET      ;06a2    c2 70 21     . p ! 
    ld a,10             ;06a5    3e 0a     > . 
    ld (CMP_SIZE),a     ;06a7    32 06 5d     2 . ] 
    ld hl,FILEPARM1     ;06aa    21 e6 5c     ! . \ 
    inc (hl)            ;06ad    34     4 
    ld a,(SRCDRIVE)     ;06ae    3a f8 5c     : . \ 
    call SEL_DRIVE01    ;06b1    cd 74 3d     . t = 
    call SEEK_STRF      ;06b4    cd 69 25     . i % 
    jp nz,DSTM_RET      ;06b7    c2 70 21     . p ! 
    call GETENTRY       ;06ba    cd ae 27     . . ' 
    ld hl,FILEPARM1     ;06bd    21 e6 5c     ! . \ 
    ld de,FILETEMP      ;06c0    11 ed 5c     . . \ 
    ld bc,7             ;06c3    01 07 00     . . . 
    ldir                ;06c6    ed b0     . . 
    ld a,(DESTDRIVE)    ;06c8    3a f9 5c     : . \ 
    call SEL_DRIVE01    ;06cb    cd 74 3d     . t = 
    call ID_TYPE        ;06ce    cd 84 23     . . # 
    jr $-58             ;06d1    18 c4     . . 
    ld a,(FILETEMP+4)   ;06d3    3a f1 5c     : . \ 
    or a                ;06d6    b7     . 
    ret z               ;06d7    c8     . 
    push hl             ;06d8    e5     . 
    ld hl,WSBUFFSIZ     ;06d9    21 23 5d     ! # ] 
    sub (hl)            ;06dc    96     . 
    pop hl              ;06dd    e1     . 
    jr nc,$+59          ;06de    30 39     0 9 
    ld a,(FILETEMP+4)   ;06e0    3a f1 5c     : . \ 
    ld b,a              ;06e3    47     G 
    xor a               ;06e4    af     . 
    ld (FILETEMP+4),a   ;06e5    32 f1 5c     2 . \ 
    push bc             ;06e8    c5     . 
    ld a,(SRCDRIVE)     ;06e9    3a f8 5c     : . \ 
    call SEL_DRIVE01    ;06ec    cd 74 3d     . t = 
    pop bc              ;06ef    c1     . 
    push bc             ;06f0    c5     . 
    ld hl,(WKSPADD)     ;06f1    2a cf 5c     * . \ 
    push hl             ;06f4    e5     . 
    ld de,(FILETEMP+5)  ;06f5    ed 5b f2 5c     . [ . \ 
    call RDSECTORS      ;06f9    cd ea 2e     . . . 
    ld hl,(RWSECID)     ;06fc    2a f4 5c     * . \ 
    ld (FILETEMP+5),hl  ;06ff    22 f2 5c     " . \ 
    ld a,(DESTDRIVE)    ;0702    3a f9 5c     : . \ 
    call SEL_DRIVE01    ;0705    cd 74 3d     . t = 
    pop hl              ;0708    e1     . 
    pop bc              ;0709    c1     . 
    ld de,(FILESECT)    ;070a    ed 5b eb 5c     . [ . \ 
    call WRSECTORS      ;070e    cd fa 2e     . . . 
    ld hl,(RWSECID)     ;0711    2a f4 5c     * . \ 
    ld (FILESECT),hl    ;0714    22 eb 5c     " . \ 
    jr $-68             ;0717    18 ba     . . 
    ld (FILETEMP+4),a   ;0719    32 f1 5c     2 . \ 
    push hl             ;071c    e5     . 
    ld hl,WSBUFFSIZ     ;071d    21 23 5d     ! # ] 
    ld b,(hl)           ;0720    46     F 
    pop hl              ;0721    e1     . 
    xor a               ;0722    af     . 
    jr $-59             ;0723    18 c3     . . 
    xor a               ;0725    af     . 
    ld (NOFILE),a       ;0726    32 07 5d     2 . ] 
    jr $+27             ;0729    18 19     . . 
    call GET1ARG_S      ;072b    cd 7c 2e     . | . 
    call SYN_CHCK       ;072e    cd 0e 2e     . . . 
    call FIND_FTYPE     ;0731    cd f1 24     . . $ 
    xor a               ;0734    af     . 
    ld (NOFILE),a       ;0735    32 07 5d     2 . ] 
    call USTK_FILE      ;0738    cd f1 38     . . 8 
    call ERASEFILE      ;073b    cd 44 27     . D ' 
    jp nz,ERASE_ENFL    ;073e    c2 27 25     . ' % 
    jp DSTM_RET         ;0741    c3 70 21     . p ! 
    ld a,(FILENAME)     ;0744    3a dd 5c     : . \ 
    ld (FSTCHAR),a      ;0747    32 08 5d     2 . ] 
    ret nz              ;074a    c0     . 
    ld hl,NOFILE        ;074b    21 07 5d     ! . ] 
    inc (hl)            ;074e    34     4 
    push bc             ;074f    c5     . 
    call READ_CS        ;0750    cd 7f 23     . © # 
    ld a,(#5BE4)        ;0753    3a e4 5b     : . [ 
    pop bc              ;0756    c1     . 
    inc c               ;0757    0c     . 
    cp c                ;0758    b9     . 
    jr nz,$+7           ;0759    20 05       . 
    dec a               ;075b    3d     = 
    ld (#5BE4),a        ;075c    32 e4 5b     2 . [ 
    xor a               ;075f    af     . 
    push af             ;0760    f5     . 
    jr z,$+6            ;0761    28 04     ( . 
    ld hl,#5BF4         ;0763    21 f4 5b     ! . [ 
    inc (hl)            ;0766    34     4 
    push bc             ;0767    c5     . 
    call WRT_BUFFER     ;0768    cd f0 2e     . . . 
    pop bc              ;076b    c1     . 
    dec c               ;076c    0d     . 
    call GETENTRY       ;076d    cd ae 27     . . ' 
    pop af              ;0770    f1     . 
    jp z,ERASEFILE03    ;0771    ca 76 27     . v ' 
    ld a,1              ;0774    3e 01     > . 
    ld (FILENAME),a     ;0776    32 dd 5c     2 . \ 
    push af             ;0779    f5     . 
    call SV_ENTRY       ;077a    cd ed 2e     . . . 
    ld a,(FSTCHAR)      ;077d    3a 08 5d     : . ] 
    ld (FILENAME),a     ;0780    32 dd 5c     2 . \ 
    pop af              ;0783    f1     . 
    jr z,$+7            ;0784    28 05     ( . 
    call SEEKFILE01     ;0786    cd 4c 2d     . L - 
    jr $-69             ;0789    18 b9     . . 
    call READ_CS        ;078b    cd 7f 23     . © # 
    ld hl,(FILESECT)    ;078e    2a eb 5c     * . \ 
    ld (#5BE1),hl       ;0791    22 e1 5b     " . [ 
    ld de,(FILESIZE)    ;0794    ed 5b ea 5c     . [ . \ 
    ld hl,(#5BE5)       ;0798    2a e5 5b     * . [ 
    ld d,0              ;079b    16 00     . . 
    add hl,de           ;079d    19     . 
    ld (#5BE5),hl       ;079e    22 e5 5b     " . [ 
    jp WRT_BUFFER       ;07a1    c3 f0 2e     . . . 
    call GETENTRY       ;07a4    cd ae 27     . . ' 
    ld a,(FILENAME)     ;07a7    3a dd 5c     : . \ 
    cp 1                ;07aa    fe 01     . . 
    ret                 ;07ac    c9     . 
    ld c,a              ;07ad    4f     O 
    xor a               ;07ae    af     . 
    push bc             ;07af    c5     . 
    call CP_ENTRY       ;07b0    cd 25 29     . % ) 
    pop bc              ;07b3    c1     . 
    ret                 ;07b4    c9     . 
    ld c,a              ;07b5    4f     O 
    call PUTENTRY       ;07b6    cd bc 27     . . ' 
    jp WRT_BUFFER       ;07b9    c3 f0 2e     . . . 
    ld a,#FF            ;07bc    3e ff     > . 
    jr $-15             ;07be    18 ef     . . 
    ld a,#FF            ;07c0    3e ff     > . 
    ld (CLR_WSP),a      ;07c2    32 0e 5d     2 . ] 
    call CHECKRAM       ;07c5    cd d1 27     . . ' 
    ld hl,(WORKSP)      ;07c8    2a 61 5c     * a \ 
    ld (WKSPADD),hl     ;07cb    22 cf 5c     " . \ 
    jp BAS_BCSPC        ;07ce    c3 c2 2e     . . . 
    ld hl,#1F1A         ;07d1    21 1a 1f     ! . . 
    call CALLBAS        ;07d4    cd 36 2e     . 6 . 
    ld hl,65535         ;07d7    21 ff ff     ! . . 
    sbc hl,bc           ;07da    ed 42     . B 
    ld a,h              ;07dc    7c     | 
    cp 16               ;07dd    fe 10     . . 
    jr nc,$+4           ;07df    30 02     0 . 
    ld a,17             ;07e1    3e 11     > . 
    dec a               ;07e3    3d     = 
    ld (WSBUFFSIZ),a    ;07e4    32 23 5d     2 # ] 
    ld b,a              ;07e7    47     G 
    ld c,0              ;07e8    0e 00     . . 
    ret                 ;07ea    c9     . 
    ld (VAR_A_L),hl     ;07eb    22 d7 5c     " . \ 
    ld (VAR_C_L),hl     ;07ee    22 db 5c     " . \ 
    ld de,(FILESIZE)    ;07f1    ed 5b ea 5c     . [ . \ 
    ld hl,(VAR_B_L)     ;07f5    2a d9 5c     * . \ 
    ld d,0              ;07f8    16 00     . . 
    add hl,de           ;07fa    19     . 
    ld (VAR_B_L),hl     ;07fb    22 d9 5c     " . \ 
    ret                 ;07fe    c9     . 
    call SYN_CHCK       ;07ff    cd 0e 2e     . . . 
    call WKSPMEM        ;0802    cd c0 27     . . ' 
    call ID_TYPE        ;0805    cd 84 23     . . # 
    ld a,(#5BF4)        ;0808    3a f4 5b     : . [ 
    or a                ;080b    b7     . 
    jp z,DSTM_RET       ;080c    ca 70 21     . p ! 
    ld hl,0             ;080f    21 00 00     ! . . 
    ld (VAR_B_L),hl     ;0812    22 d9 5c     " . \ 
    ld c,#FF            ;0815    0e ff     . . 
    inc c               ;0817    0c     . 
    call CHKDELET       ;0818    cd a4 27     . . ' 
    jr nz,$-4           ;081b    20 fa       . 
    ld a,c              ;081d    79     y 
    ld (ERASEDFL),a     ;081e    32 d4 5c     2 . \ 
    ld hl,(FILESECT)    ;0821    2a eb 5c     * . \ 
    ld (ERASEDSC),hl    ;0824    22 d5 5c     " . \ 
    call FREEDSCT       ;0827    cd eb 27     . . ' 
    inc c               ;082a    0c     . 
    call CHKDELET       ;082b    cd a4 27     . . ' 
    jr z,$-4            ;082e    28 fa     ( . 
    cp 0                ;0830    fe 00     . . 
    jr nz,$+26          ;0832    20 18       . 
    ld a,(ERASEDFL)     ;0834    3a d4 5c     : . \ 
    ld c,a              ;0837    4f     O 
    inc c               ;0838    0c     . 
    call CHKDELET       ;0839    cd a4 27     . . ' 
    cp 0                ;083c    fe 00     . . 
    jr z,$+106          ;083e    28 68     ( h 
    xor a               ;0840    af     . 
    ld (FILENAME),a     ;0841    32 dd 5c     2 . \ 
    call SV_ENTRY       ;0844    cd ed 2e     . . . 
    call FREEDSCT       ;0847    cd eb 27     . . ' 
    jr $-18             ;084a    18 ec     . . 
    ld a,(FILESIZE)     ;084c    3a ea 5c     : . \ 
    ld (NSECMOV),a      ;084f    32 d3 5c     2 . \ 
    ld (NODISK),a       ;0852    32 d1 5c     2 . \ 
    ld hl,(FILESECT)    ;0855    2a eb 5c     * . \ 
    ld (ERASEDSC),hl    ;0858    22 d5 5c     " . \ 
    push bc             ;085b    c5     . 
    call MOVESECT       ;085c    cd e1 28     . . ( 
    pop bc              ;085f    c1     . 
    ld hl,(RWSECID)     ;0860    2a f4 5c     * . \ 
    ld (ERASEDSC),hl    ;0863    22 d5 5c     " . \ 
    ld (FILESECT),hl    ;0866    22 eb 5c     " . \ 
    xor a               ;0869    af     . 
    ld (FILESIZE),a     ;086a    32 ea 5c     2 . \ 
    ld a,(FILENAME)     ;086d    3a dd 5c     : . \ 
    push af             ;0870    f5     . 
    ld a,1              ;0871    3e 01     > . 
    ld (FILENAME),a     ;0873    32 dd 5c     2 . \ 
    call SV_ENTRY       ;0876    cd ed 2e     . . . 
    pop af              ;0879    f1     . 
    ld (FILENAME),a     ;087a    32 dd 5c     2 . \ 
    ld a,(ERASEDFL)     ;087d    3a d4 5c     : . \ 
    ld c,a              ;0880    4f     O 
    ld hl,(VAR_C_L)     ;0881    2a db 5c     * . \ 
    ld (FILESECT),hl    ;0884    22 eb 5c     " . \ 
    ld a,(NODISK)       ;0887    3a d1 5c     : . \ 
    ld (FILESIZE),a     ;088a    32 ea 5c     2 . \ 
    call SV_ENTRY       ;088d    cd ed 2e     . . . 
    ld a,(ERASEDFL)     ;0890    3a d4 5c     : . \ 
    inc a               ;0893    3c     < 
    ld c,a              ;0894    4f     O 
    call GETENTRY       ;0895    cd ae 27     . . ' 
    ld hl,(ERASEDSC)    ;0898    2a d5 5c     * . \ 
    ld (FILESECT),hl    ;089b    22 eb 5c     " . \ 
    call SV_ENTRY       ;089e    cd ed 2e     . . . 
    ld a,(ERASEDFL)     ;08a1    3a d4 5c     : . \ 
    ld c,a              ;08a4    4f     O 
    jp DS_MOVE01        ;08a5    c3 17 28     . . ( 
    ld hl,(WKSPADD)     ;08a8    2a cf 5c     * . \ 
    ld bc,#1000         ;08ab    01 00 10     . . . 
    call BAS_RECLM      ;08ae    cd d7 2e     . . . 
    call READ_CS        ;08b1    cd 7f 23     . © # 
    ld hl,(#5BE5)       ;08b4    2a e5 5b     * . [ 
    ld de,(VAR_B_L)     ;08b7    ed 5b d9 5c     . [ . \ 
    add hl,de           ;08bb    19     . 
    ld (#5BE5),hl       ;08bc    22 e5 5b     " . [ 
    ld a,(#5BE4)        ;08bf    3a e4 5b     : . [ 
    ld hl,#5BF4         ;08c2    21 f4 5b     ! . [ 
    sub (hl)            ;08c5    96     . 
    ld (#5BE4),a        ;08c6    32 e4 5b     2 . [ 
    ld (hl),0           ;08c9    36 00     6 . 
    ld hl,(ERASEDSC)    ;08cb    2a d5 5c     * . \ 
    ld (#5BE1),hl       ;08ce    22 e1 5b     " . [ 
    push af             ;08d1    f5     . 
    call WRT_BUFFER     ;08d2    cd f0 2e     . . . 
    pop af              ;08d5    f1     . 
    ld c,a              ;08d6    4f     O 
    call GETENTRY       ;08d7    cd ae 27     . . ' 
    xor a               ;08da    af     . 
    ld (FILENAME),a     ;08db    32 dd 5c     2 . \ 
    jp DIR_RET          ;08de    c3 e6 24     . . $ 
    ld a,(NSECMOV)      ;08e1    3a d3 5c     : . \ 
    or a                ;08e4    b7     . 
    ret z               ;08e5    c8     . 
    push hl             ;08e6    e5     . 
    ld hl,WSBUFFSIZ     ;08e7    21 23 5d     ! # ] 
    sub (hl)            ;08ea    96     . 
    pop hl              ;08eb    e1     . 
    jr nc,$+45          ;08ec    30 2b     0 + 
    ld a,(NSECMOV)      ;08ee    3a d3 5c     : . \ 
    ld b,a              ;08f1    47     G 
    xor a               ;08f2    af     . 
    ld (NSECMOV),a      ;08f3    32 d3 5c     2 . \ 
    push bc             ;08f6    c5     . 
    ld hl,(WKSPADD)     ;08f7    2a cf 5c     * . \ 
    push hl             ;08fa    e5     . 
    ld de,(ERASEDSC)    ;08fb    ed 5b d5 5c     . [ . \ 
    call RDSECTORS      ;08ff    cd ea 2e     . . . 
    ld hl,(RWSECID)     ;0902    2a f4 5c     * . \ 
    ld (ERASEDSC),hl    ;0905    22 d5 5c     " . \ 
    pop hl              ;0908    e1     . 
    pop bc              ;0909    c1     . 
    ld de,(VAR_A_L)     ;090a    ed 5b d7 5c     . [ . \ 
    call WRSECTORS      ;090e    cd fa 2e     . . . 
    ld hl,(RWSECID)     ;0911    2a f4 5c     * . \ 
    ld (VAR_A_L),hl     ;0914    22 d7 5c     " . \ 
    jr $-54             ;0917    18 c8     . . 
    ld (NSECMOV),a      ;0919    32 d3 5c     2 . \ 
    push hl             ;091c    e5     . 
    ld hl,WSBUFFSIZ     ;091d    21 23 5d     ! # ] 
    ld b,(hl)           ;0920    46     F 
    pop hl              ;0921    e1     . 
    xor a               ;0922    af     . 
    jr $-45             ;0923    18 d1     . . 
    push af             ;0925    f5     . 
    ld hl,TRK0SECT      ;0926    21 cc 5c     ! . \ 
    ld (hl),0           ;0929    36 00     6 . 
    ld a,c              ;092b    79     y 
    sub 16              ;092c    d6 10     . . 
    jr c,$+5            ;092e    38 03     8 . 
    inc (hl)            ;0930    34     4 
    jr $-5              ;0931    18 f9     . . 
    add a,16            ;0933    c6 10     . . 
    ld c,a              ;0935    4f     O 
    push bc             ;0936    c5     . 
    call READT0SX       ;0937    cd 64 23     . d # 
    pop bc              ;093a    c1     . 
    pop af              ;093b    f1     . 
    call DIRENTRYPOS    ;093c    cd 3d 2d     . = - 
    ld de,FILENAME      ;093f    11 dd 5c     . . \ 
    ld bc,16            ;0942    01 10 00     . . . 
    or a                ;0945    b7     . 
    jr z,$+3            ;0946    28 01     ( . 
    ex de,hl            ;0948    eb     . 
    ldir                ;0949    ed b0     . . 
    ret                 ;094b    c9     . 
    call RS_LDEXEC      ;094c    cd 81 29     . . ) 
    call FILELOAD       ;094f    cd 65 29     . e ) 
    call SYN_CHCK       ;0952    cd 0e 2e     . . . 
    ld a,#FF            ;0955    3e ff     > . 
    ld (LDPKEXEC),a     ;0957    32 10 5d     2 . ] 
    ld a,(FILETYPE)     ;095a    3a e5 5c     : . \ 
    cp #42              ;095d    fe 42     . B 
    jp z,EXEC_BAS       ;095f    ca f1 20     . .   
    jp DSTM_RET         ;0962    c3 70 21     . p ! 
    call LOADARG        ;0965    cd a9 29     . . ) 
    call SYN_CHCK       ;0968    cd 0e 2e     . . . 
    call LOADPARM       ;096b    cd dd 29     . . ) 
    jp FILELOAD01       ;096e    c3 4d 2a     . M * 
    ld hl,(CH_ADD)      ;0971    2a 5d 5c     * ] \ 
    inc hl              ;0974    23     # 
    ld a,(hl)           ;0975    7e     ~ 
    cp #0D              ;0976    fe 0d     . . 
    ret z               ;0978    c8     . 
    ld a,1              ;0979    3e 01     > . 
    ld (CODEARG),a      ;097b    32 d6 5c     2 . \ 
    call PARAM_C01      ;097e    cd 88 2e     . . . 
    xor a               ;0981    af     . 
    ld (LDPKEXEC),a     ;0982    32 10 5d     2 . ] 
    ret                 ;0985    c9     . 
    call FIND_FTYPE     ;0986    cd f1 24     . . $ 
    ld a,#42            ;0989    3e 42     > B 
    cp b                ;098b    b8     . 
    jr nz,$+9           ;098c    20 07       . 
    ld hl,(CH_ADD)      ;098e    2a 5d 5c     * ] \ 
    dec hl              ;0991    2b     + 
    ld (CH_ADD),hl      ;0992    22 5d 5c     " ] \ 
    call PARAM_C01      ;0995    cd 88 2e     . . . 
    ld hl,(VAR_B_L)     ;0998    2a d9 5c     * . \ 
    ld (VAR_A_L),hl     ;099b    22 d7 5c     " . \ 
    ld hl,(VAR_C_L)     ;099e    2a db 5c     * . \ 
    ld (VAR_B_L),hl     ;09a1    22 d9 5c     " . \ 
    xor a               ;09a4    af     . 
    ld (CODEARG),a      ;09a5    32 d6 5c     2 . \ 
    ret                 ;09a8    c9     . 
    call NOARG          ;09a9    cd aa 23     . . # 
    jp z,RUNBOOT        ;09ac    ca 0d 22     . . " 
    call GET1ARG_S      ;09af    cd 7c 2e     . | . 
    call CHK_LDPK       ;09b2    cd ec 24     . . $ 
    call nz,PK_ARG      ;09b5    c4 86 29     . . ) 
    call BAS_GETCHR     ;09b8    cd 26 2e     . & . 
    cp #AF              ;09bb    fe af     . . 
    call z,LDCD_ARG     ;09bd    cc 71 29     . q ) 
    cp #E4              ;09c0    fe e4     . . 
    push af             ;09c2    f5     . 
    call CHK_LDPK       ;09c3    cd ec 24     . . $ 
    call z,FIND_FTYPE   ;09c6    cc f1 24     . . $ 
    pop af              ;09c9    f1     . 
    call z,FETARRAY     ;09ca    cc ab 2c     . . , 
    call SYN_CHCK       ;09cd    cd 0e 2e     . . . 
    call USTK_FILE      ;09d0    cd f1 38     . . 8 
    jp nz,ER_NOFILE     ;09d3    c2 58 23     . X # 
    call GETENTRY       ;09d6    cd ae 27     . . ' 
    call LOADBUFF       ;09d9    cd 96 3f     . . ? 
    ret                 ;09dc    c9     . 
    ld a,(CODEARG)      ;09dd    3a d6 5c     : . \ 
    or a                ;09e0    b7     . 
    ld hl,(FILEPARM1)   ;09e1    2a e6 5c     * . \ 
    jr z,$+5            ;09e4    28 03     ( . 
    ld hl,(VAR_B_L)     ;09e6    2a d9 5c     * . \ 
    ld de,(FILESECT)    ;09e9    ed 5b eb 5c     . [ . \ 
    cp 3                ;09ed    fe 03     . . 
    ld a,(FILESIZE)     ;09ef    3a ea 5c     : . \ 
    push de             ;09f2    d5     . 
    ld de,(FILEPARM2)   ;09f3    ed 5b e8 5c     . [ . \ 
    jr nz,$+6           ;09f7    20 04       . 
    ld de,(VAR_C_L)     ;09f9    ed 5b db 5c     . [ . \ 
    ld b,a              ;09fd    47     G 
    ld (VAR_C_L),de     ;09fe    ed 53 db 5c     . S . \ 
    ld a,(FILETYPE)     ;0a02    3a e5 5c     : . \ 
    cp #43              ;0a05    fe 43     . C 
    ld a,b              ;0a07    78     x 
    jr nz,$+41          ;0a08    20 27       ' 
    ld a,b              ;0a0a    78     x 
    cp d                ;0a0b    ba     . 
    jr z,$+28           ;0a0c    28 1a     ( . 
    dec a               ;0a0e    3d     = 
    cp d                ;0a0f    ba     . 
    ld a,b              ;0a10    78     x 
    jr z,$+23           ;0a11    28 15     ( . 
    ld a,(CODEARG)      ;0a13    3a d6 5c     : . \ 
    cp 3                ;0a16    fe 03     . . 
    ld a,b              ;0a18    78     x 
    jr z,$+15           ;0a19    28 0d     ( . 
    xor a               ;0a1b    af     . 
    ld (CODEARG),a      ;0a1c    32 d6 5c     2 . \ 
    ld d,b              ;0a1f    50     P 
    ld e,0              ;0a20    1e 00     . . 
    ld (VAR_C_L),de     ;0a22    ed 53 db 5c     . S . \ 
    jr $+7              ;0a26    18 05     . . 
    ld a,3              ;0a28    3e 03     > . 
    ld (CODEARG),a      ;0a2a    32 d6 5c     2 . \ 
    ld a,b              ;0a2d    78     x 
    call TRUNCLEN       ;0a2e    cd 59 2f     . Y / 
    push af             ;0a31    f5     . 
    ld a,h              ;0a32    7c     | 
    cp #5B              ;0a33    fe 5b     . [ 
    jr nz,$+6           ;0a35    20 04       . 
    xor a               ;0a37    af     . 
    ld (CODEARG),a      ;0a38    32 d6 5c     2 . \ 
    ld a,(FILETYPE)     ;0a3b    3a e5 5c     : . \ 
    cp #42              ;0a3e    fe 42     . B 
    push af             ;0a40    f5     . 
    call z,MKBASROOM    ;0a41    cc d3 2a     . . * 
    pop af              ;0a44    f1     . 
    cp #44              ;0a45    fe 44     . D 
    call z,MKARRROOM    ;0a47    cc 03 2b     . . + 
    pop af              ;0a4a    f1     . 
    pop de              ;0a4b    d1     . 
    ret                 ;0a4c    c9     . 
    ld b,a              ;0a4d    47     G 
    call CHK_LDPK       ;0a4e    cd ec 24     . . $ 
    jr z,$+9            ;0a51    28 07     ( . 
    push af             ;0a53    f5     . 
    call SCT_OFF        ;0a54    cd 3e 2b     . > + 
    pop af              ;0a57    f1     . 
    cp #FF              ;0a58    fe ff     . . 
    push af             ;0a5a    f5     . 
    call z,RDSECTORS    ;0a5b    cc ea 2e     . . . 
    pop af              ;0a5e    f1     . 
    jr z,$+5            ;0a5f    28 03     ( . 
    jp WRSECTORS        ;0a61    c3 fa 2e     . . . 
    ld a,(CODEARG)      ;0a64    3a d6 5c     : . \ 
    cp 3                ;0a67    fe 03     . . 
    call z,LASTSECTOR   ;0a69    cc ae 3f     . . ? 
    ld hl,(E_LINE)      ;0a6c    2a 59 5c     * Y \ 
    dec hl              ;0a6f    2b     + 
    ld (hl),#80         ;0a70    36 80     6 . 
    ret                 ;0a72    c9     . 
    ld a,#FF            ;0a73    3e ff     > . 
    jr $+4              ;0a75    18 02     . . 
    ld a,#EE            ;0a77    3e ee     > . 
    ld (LDPKEXEC),a     ;0a79    32 10 5d     2 . ] 
    jp PEEKPOKE01       ;0a7c    c3 4f 29     . O ) 
    ld a,#FF            ;0a7f    3e ff     > . 
    ld (RM_FPC),a       ;0a81    32 1f 5d     2 . ] 
    call LOADARG        ;0a84    cd a9 29     . . ) 
    call SYN_CHCK       ;0a87    cd 0e 2e     . . . 
    ld a,(FILETYPE)     ;0a8a    3a e5 5c     : . \ 
    cp #42              ;0a8d    fe 42     . B 
    jp nz,ER_SYNTX      ;0a8f    c2 b3 2d     . . - 
    ld bc,(FILEPARM1)   ;0a92    ed 4b e6 5c     . K . \ 
    push bc             ;0a96    c5     . 
    inc bc              ;0a97    03     . 
    ld hl,#30           ;0a98    21 30 00     ! 0 . 
    call CALLBAS        ;0a9b    cd 36 2e     . 6 . 
    ld (hl),#80         ;0a9e    36 80     6 . 
    ex de,hl            ;0aa0    eb     . 
    pop de              ;0aa1    d1     . 
    push hl             ;0aa2    e5     . 
    ld de,(FILESECT)    ;0aa3    ed 5b eb 5c     . [ . \ 
    ld a,(FILESIZE)     ;0aa7    3a ea 5c     : . \ 
    ld b,a              ;0aaa    47     G 
    call RS_LDEXEC      ;0aab    cd 81 29     . . ) 
    ld a,b              ;0aae    78     x 
    call FILELOAD01     ;0aaf    cd 4d 2a     . M * 
    pop hl              ;0ab2    e1     . 
    rst 32              ;0ab3    e7     . 
    ld de,(PROG)        ;0ab4    ed 5b 53 5c     . [ S \ 
    ld hl,#08D2         ;0ab8    21 d2 08     ! . . 
    call CALLBASHL      ;0abb    cd cf 2e     . . . 
    jp DSTM_RET         ;0abe    c3 70 21     . p ! 
    ex de,hl            ;0ac1    eb     . 
    scf                 ;0ac2    37     7 
    sbc hl,de           ;0ac3    ed 52     . R 
    ret c               ;0ac5    d8     . 
    ld de,#000A         ;0ac6    11 0a 00     . . . 
    add hl,de           ;0ac9    19     . 
    ld b,h              ;0aca    44     D 
    ld c,l              ;0acb    4d     M 
    ld hl,#1F05         ;0acc    21 05 1f     ! . . 
    call CALLBAS        ;0acf    cd 36 2e     . 6 . 
    ret                 ;0ad2    c9     . 
    ld de,(PROG)        ;0ad3    ed 5b 53 5c     . [ S \ 
    ld hl,(E_LINE)      ;0ad7    2a 59 5c     * Y \ 
    dec hl              ;0ada    2b     + 
    push hl             ;0adb    e5     . 
    push de             ;0adc    d5     . 
    sbc hl,de           ;0add    ed 52     . R 
    ld de,(FILEPARM1)   ;0adf    ed 5b e6 5c     . [ . \ 
    push de             ;0ae3    d5     . 
    call TESTSPACE      ;0ae4    cd c1 2a     . . * 
    pop bc              ;0ae7    c1     . 
    pop de              ;0ae8    d1     . 
    pop hl              ;0ae9    e1     . 
    push bc             ;0aea    c5     . 
    rst 32              ;0aeb    e7     . 
    ld hl,#19E5         ;0aec    21 e5 19     ! . . 
    call CALLBASHL      ;0aef    cd cf 2e     . . . 
    pop bc              ;0af2    c1     . 
    call BAS_MKROOM     ;0af3    cd dd 2e     . . . 
    inc hl              ;0af6    23     # 
    ld bc,(FILEPARM2)   ;0af7    ed 4b e8 5c     . K . \ 
    add hl,bc           ;0afb    09     . 
    ld (VARS),hl        ;0afc    22 4b 5c     " K \ 
    ld hl,(PROG)        ;0aff    2a 53 5c     * S \ 
    ret                 ;0b02    c9     . 
    ld de,(FILEPARM2)   ;0b03    ed 5b e8 5c     . [ . \ 
    ld hl,(VAR_B_L)     ;0b07    2a d9 5c     * . \ 
    push hl             ;0b0a    e5     . 
    call TESTSPACE      ;0b0b    cd c1 2a     . . * 
    pop hl              ;0b0e    e1     . 
    ld a,h              ;0b0f    7c     | 
    or l                ;0b10    b5     . 
    jr z,$+18           ;0b11    28 10     ( . 
    ld hl,(VAR_A_L)     ;0b13    2a d7 5c     * . \ 
    dec hl              ;0b16    2b     + 
    dec hl              ;0b17    2b     + 
    dec hl              ;0b18    2b     + 
    ld bc,(VAR_B_L)     ;0b19    ed 4b d9 5c     . K . \ 
    inc bc              ;0b1d    03     . 
    inc bc              ;0b1e    03     . 
    inc bc              ;0b1f    03     . 
    call BAS_RECLM      ;0b20    cd d7 2e     . . . 
    ld hl,(E_LINE)      ;0b23    2a 59 5c     * Y \ 
    dec hl              ;0b26    2b     + 
    ld bc,(FILEPARM2)   ;0b27    ed 4b e8 5c     . K . \ 
    push bc             ;0b2b    c5     . 
    inc bc              ;0b2c    03     . 
    inc bc              ;0b2d    03     . 
    inc bc              ;0b2e    03     . 
    call BAS_MKROOM     ;0b2f    cd dd 2e     . . . 
    inc hl              ;0b32    23     # 
    ld a,(VARNAME)      ;0b33    3a d2 5c     : . \ 
    ld (hl),a           ;0b36    77     w 
    inc hl              ;0b37    23     # 
    pop de              ;0b38    d1     . 
    ld (hl),e           ;0b39    73     s 
    inc hl              ;0b3a    23     # 
    ld (hl),d           ;0b3b    72     r 
    inc hl              ;0b3c    23     # 
    ret                 ;0b3d    c9     . 
    ld a,(VAR_B_L)      ;0b3e    3a d9 5c     : . \ 
    ld c,b              ;0b41    48     H 
    ld b,a              ;0b42    47     G 
    ld a,c              ;0b43    79     y 
    cp b                ;0b44    b8     . 
    jr c,$+27           ;0b45    38 19     8 . 
    ld a,b              ;0b47    78     x 
    or a                ;0b48    b7     . 
    jp z,ER_SYNTX       ;0b49    ca b3 2d     . . - 
    dec b               ;0b4c    05     . 
    jr z,$+13           ;0b4d    28 0b     ( . 
    ld a,16             ;0b4f    3e 10     > . 
    inc e               ;0b51    1c     . 
    cp e                ;0b52    bb     . 
    jr nz,$+5           ;0b53    20 03       . 
    ld e,0              ;0b55    1e 00     . . 
    inc d               ;0b57    14     . 
    djnz $-7            ;0b58    10 f7     . . 
    ld b,1              ;0b5a    06 01     . . 
    ld hl,(VAR_A_L)     ;0b5c    2a d7 5c     * . \ 
    ret                 ;0b5f    c9     . 
    ld hl,M_RECOF       ;0b60    21 92 39     ! . 9 
    ld a,5              ;0b63    3e 05     > . 
    jp DSTM_ERRET       ;0b65    c3 e5 2c     . . , 
    call USTK_FILE      ;0b68    cd f1 38     . . 8 
    jp z,ER_F_EXIST     ;0b6b    ca eb 2c     . . , 
    call READ_CS        ;0b6e    cd 7f 23     . © # 
    ld a,(#5BE4)        ;0b71    3a e4 5b     : . [ 
    cp #80              ;0b74    fe 80     . . 
    jp z,ER_DIRFULL     ;0b76    ca 97 37     . . 7 
    ret                 ;0b79    c9     . 
    call RS_LDEXEC      ;0b7a    cd 81 29     . . ) 
    ld hl,0             ;0b7d    21 00 00     ! . . 
    ld (NODISK),hl      ;0b80    22 d1 5c     " . \ 
    call GET1ARG_S      ;0b83    cd 7c 2e     . | . 
    call BAS_GETCHR     ;0b86    cd 26 2e     . & . 
    cp #AF              ;0b89    fe af     . . 
    jr z,$+88           ;0b8b    28 56     ( V 
    cp #CA              ;0b8d    fe ca     . . 
    jr nz,$+19          ;0b8f    20 11       . 
    call GETARG_I       ;0b91    cd a8 2e     . . . 
    call SYN_CHCK       ;0b94    cd 0e 2e     . . . 
    ld hl,(VAR_C_L)     ;0b97    2a db 5c     * . \ 
    ld (NODISK),hl      ;0b9a    22 d1 5c     " . \ 
    ld hl,FILETYPE      ;0b9d    21 e5 5c     ! . \ 
    jr $+41             ;0ba0    18 27     . ' 
    cp #AA              ;0ba2    fe aa     . . 
    jr nz,$+19          ;0ba4    20 11       . 
    ld hl,VID_RAM       ;0ba6    21 00 40     ! . @ 
    ld (VAR_A_L),hl     ;0ba9    22 d7 5c     " . \ 
    ld hl,#1B00         ;0bac    21 00 1b     ! . . 
    ld (VAR_B_L),hl     ;0baf    22 d9 5c     " . \ 
    ld (VAR_C_L),hl     ;0bb2    22 db 5c     " . \ 
    jr $+61             ;0bb5    18 3b     . ; 
    call SYN_CHCK       ;0bb7    cd 0e 2e     . . . 
    call BAS_GETCHR     ;0bba    cd 26 2e     . & . 
    ld hl,FILETYPE      ;0bbd    21 e5 5c     ! . \ 
    cp #E4              ;0bc0    fe e4     . . 
    jr z,$+20           ;0bc2    28 12     ( . 
    cp #0D              ;0bc4    fe 0d     . . 
    jp nz,ER_SYNTX      ;0bc6    c2 b3 2d     . . - 
    ld (hl),#42         ;0bc9    36 42     6 B 
    call FILEXIST       ;0bcb    cd 68 2b     . h + 
    call BAS_RMFP       ;0bce    cd b9 2e     . . . 
    call PARAM_B        ;0bd1    cd 8d 2c     . . , 
    jr $+41             ;0bd4    18 27     . ' 
    ld (hl),#44         ;0bd6    36 44     6 D 
    call FILEXIST       ;0bd8    cd 68 2b     . h + 
    call PARAM_D        ;0bdb    cd b6 2c     . . , 
    jr nc,$+31          ;0bde    30 1d     0 . 
    jp c,ER_SYNTX       ;0be0    da b3 2d     . . - 
    call PARAM_C        ;0be3    cd 82 2e     . . . 
    ld hl,(VAR_B_L)     ;0be6    2a d9 5c     * . \ 
    ld (VAR_A_L),hl     ;0be9    22 d7 5c     " . \ 
    ld hl,(VAR_C_L)     ;0bec    2a db 5c     * . \ 
    ld (VAR_B_L),hl     ;0bef    22 d9 5c     " . \ 
    call SYN_CHCK       ;0bf2    cd 0e 2e     . . . 
    ld a,#43            ;0bf5    3e 43     > C 
    ld (FILETYPE),a     ;0bf7    32 e5 5c     2 . \ 
    call FILEXIST       ;0bfa    cd 68 2b     . h + 
    call SAVEFILE       ;0bfd    cd 03 2c     . . , 
    jp DIR_RET          ;0c00    c3 e6 24     . . $ 
    ld hl,(VAR_A_L)     ;0c03    2a d7 5c     * . \ 
    ld (FILEPARM1),hl   ;0c06    22 e6 5c     " . \ 
    ex de,hl            ;0c09    eb     . 
    ld hl,(VAR_B_L)     ;0c0a    2a d9 5c     * . \ 
    ld a,l              ;0c0d    7d     } 
    or h                ;0c0e    b4     . 
    jp z,ER_SYNTX       ;0c0f    ca b3 2d     . . - 
    ld a,l              ;0c12    7d     } 
    or a                ;0c13    b7     . 
    jr z,$+3            ;0c14    28 01     ( . 
    inc h               ;0c16    24     $ 
    ld a,h              ;0c17    7c     | 
    ld (FILESIZE),a     ;0c18    32 ea 5c     2 . \ 
    ld e,a              ;0c1b    5f     _ 
    ld d,0              ;0c1c    16 00     . . 
    ld hl,(#5BE5)       ;0c1e    2a e5 5b     * . [ 
    sbc hl,de           ;0c21    ed 52     . R 
    jp c,ER_NOSPACE     ;0c23    da e0 2c     . . , 
    push hl             ;0c26    e5     . 
    ld hl,(E_LINE)      ;0c27    2a 59 5c     * Y \ 
    ld (hl),#AA         ;0c2a    36 aa     6 . 
    inc hl              ;0c2c    23     # 
    ld de,(NODISK)      ;0c2d    ed 5b d1 5c     . [ . \ 
    ld (hl),e           ;0c31    73     s 
    inc hl              ;0c32    23     # 
    ld (hl),d           ;0c33    72     r 
    ld hl,(VAR_C_L)     ;0c34    2a db 5c     * . \ 
    ld (FILEPARM2),hl   ;0c37    22 e8 5c     " . \ 
    ld hl,(#5BE1)       ;0c3a    2a e1 5b     * . [ 
    ld (FILESECT),hl    ;0c3d    22 eb 5c     " . \ 
    push hl             ;0c40    e5     . 
    call LOADBUFF01     ;0c41    cd 9b 3f     . . ? 
    pop hl              ;0c44    e1     . 
    ex de,hl            ;0c45    eb     . 
    ld hl,(FILEPARM1)   ;0c46    2a e6 5c     * . \ 
    ld a,(FILESIZE)     ;0c49    3a ea 5c     : . \ 
    ld b,a              ;0c4c    47     G 
    call WRSECTORS      ;0c4d    cd fa 2e     . . . 
    ld hl,(RWSECID)     ;0c50    2a f4 5c     * . \ 
    push hl             ;0c53    e5     . 
    call READ_CS        ;0c54    cd 7f 23     . © # 
    pop hl              ;0c57    e1     . 
    ld (#5BE1),hl       ;0c58    22 e1 5b     " . [ 
    pop hl              ;0c5b    e1     . 
    ld (#5BE5),hl       ;0c5c    22 e5 5b     " . [ 
    ld hl,#5BE4         ;0c5f    21 e4 5b     ! . [ 
    ld a,(hl)           ;0c62    7e     ~ 
    ld (FILEPOS),a      ;0c63    32 1e 5d     2 . ] 
    inc (hl)            ;0c66    34     4 
    push hl             ;0c67    e5     . 
    call WRT_BUFFER     ;0c68    cd f0 2e     . . . 
    pop hl              ;0c6b    e1     . 
    ld c,(hl)           ;0c6c    4e     N 
    dec c               ;0c6d    0d     . 
    ld a,(FILETYPE)     ;0c6e    3a e5 5c     : . \ 
    cp #42              ;0c71    fe 42     . B 
    call z,SIZE_BAS     ;0c73    cc 77 2c     . w , 
    ret                 ;0c76    c9     . 
    ld hl,(E_LINE)      ;0c77    2a 59 5c     * Y \ 
    ld de,(PROG)        ;0c7a    ed 5b 53 5c     . [ S \ 
    scf                 ;0c7e    37     7 
    sbc hl,de           ;0c7f    ed 52     . R 
    ld (FILEPARM1),hl   ;0c81    22 e6 5c     " . \ 
    ld hl,(VARS)        ;0c84    2a 4b 5c     * K \ 
    sbc hl,de           ;0c87    ed 52     . R 
    ld (FILEPARM2),hl   ;0c89    22 e8 5c     " . \ 
    ret                 ;0c8c    c9     . 
    ld hl,(VARS)        ;0c8d    2a 4b 5c     * K \ 
    ld de,(PROG)        ;0c90    ed 5b 53 5c     . [ S \ 
    sbc hl,de           ;0c94    ed 52     . R 
    ld (VAR_C_L),hl     ;0c96    22 db 5c     " . \ 
    ld hl,(PROG)        ;0c99    2a 53 5c     * S \ 
    ld (VAR_A_L),hl     ;0c9c    22 d7 5c     " . \ 
    ld hl,(E_LINE)      ;0c9f    2a 59 5c     * Y \ 
    inc hl              ;0ca2    23     # 
    inc hl              ;0ca3    23     # 
    inc hl              ;0ca4    23     # 
    sbc hl,de           ;0ca5    ed 52     . R 
    ld (VAR_B_L),hl     ;0ca7    22 d9 5c     " . \ 
    ret                 ;0caa    c9     . 
    call PARAM_D        ;0cab    cd b6 2c     . . , 
    ret nc              ;0cae    d0     . 
    ld hl,0             ;0caf    21 00 00     ! . . 
    ld (VAR_B_L),hl     ;0cb2    22 d9 5c     " . \ 
    ret                 ;0cb5    c9     . 
    call BAS_NXTCHR     ;0cb6    cd cb 2e     . . . 
    call BAS_LKVAR      ;0cb9    cd 3b 2e     . ; . 
    set 7,c             ;0cbc    cb f9     . . 
    ld a,c              ;0cbe    79     y 
    ld (VARNAME),a      ;0cbf    32 d2 5c     2 . \ 
    jr nc,$+4           ;0cc2    30 02     0 . 
    scf                 ;0cc4    37     7 
    ret                 ;0cc5    c9     . 
    jr nz,$-2           ;0cc6    20 fc       . 
    inc hl              ;0cc8    23     # 
    ld e,(hl)           ;0cc9    5e     ^ 
    inc hl              ;0cca    23     # 
    ld d,(hl)           ;0ccb    56     V 
    inc hl              ;0ccc    23     # 
    ld (VAR_A_L),hl     ;0ccd    22 d7 5c     " . \ 
    ld (VAR_C_L),de     ;0cd0    ed 53 db 5c     . S . \ 
    ld (VAR_B_L),de     ;0cd4    ed 53 d9 5c     . S . \ 
    call BAS_NXTCHR     ;0cd8    cd cb 2e     . . . 
    cp #29              ;0cdb    fe 29     . ) 
    jr nz,$-23          ;0cdd    20 e7       . 
    ret                 ;0cdf    c9     . 
    ld hl,M_NOSPACE     ;0ce0    21 60 39     ! ` 9 
    ld a,3              ;0ce3    3e 03     > . 
    call PRINTERR       ;0ce5    cd 42 23     . B # 
    jp DSTM_RET         ;0ce8    c3 70 21     . p ! 
    ld hl,M_F_EXIST     ;0ceb    21 6a 39     ! j 9 
    ld a,2              ;0cee    3e 02     > . 
    jr $-11             ;0cf0    18 f3     . . 
    ld hl,FILENAME      ;0cf2    21 dd 5c     ! . \ 
    ld b,%00001000      ;0cf5    06 08     . . 
    ld (hl),32          ;0cf7    36 20     6   
    inc hl              ;0cf9    23     # 
    djnz $-3            ;0cfa    10 fb     . . 
    call USTK_STR       ;0cfc    cd 98 24     . . $ 
    ex de,hl            ;0cff    eb     . 
    call GET_DRV        ;0d00    cd 1a 2d     . . - 
    ld a,c              ;0d03    79     y 
    or a                ;0d04    b7     . 
    jp z,ER_SYNTX       ;0d05    ca b3 2d     . . - 
    cp 9                ;0d08    fe 09     . . 
    jr c,$+4            ;0d0a    38 02     8 . 
    ld c,%00001000      ;0d0c    0e 08     . . 
    ld a,(hl)           ;0d0e    7e     ~ 
    cp 32               ;0d0f    fe 20     .   
    jp c,ER_SYNTX       ;0d11    da b3 2d     . . - 
    ld de,FILENAME      ;0d14    11 dd 5c     . . \ 
    ldir                ;0d17    ed b0     . . 
    ret                 ;0d19    c9     . 
    inc hl              ;0d1a    23     # 
    ld a,(hl)           ;0d1b    7e     ~ 
    cp #3A              ;0d1c    fe 3a     . : 
    jr nz,$+19          ;0d1e    20 11       . 
    dec hl              ;0d20    2b     + 
    ld a,(hl)           ;0d21    7e     ~ 
    call DRIVENUM       ;0d22    cd 8b 24     . . $ 
    push bc             ;0d25    c5     . 
    push hl             ;0d26    e5     . 
    call SEL_DRIVE01    ;0d27    cd 74 3d     . t = 
    pop hl              ;0d2a    e1     . 
    pop bc              ;0d2b    c1     . 
    dec bc              ;0d2c    0b     . 
    dec bc              ;0d2d    0b     . 
    inc hl              ;0d2e    23     # 
    inc hl              ;0d2f    23     # 
    ret                 ;0d30    c9     . 
    dec hl              ;0d31    2b     + 
    ld a,(DEFLTDRV)     ;0d32    3a 19 5d     : . ] 
    push bc             ;0d35    c5     . 
    push hl             ;0d36    e5     . 
    call SEL_DRIVE01    ;0d37    cd 74 3d     . t = 
    pop hl              ;0d3a    e1     . 
    pop bc              ;0d3b    c1     . 
    ret                 ;0d3c    c9     . 
    ld l,c              ;0d3d    69     i 
    ld h,0              ;0d3e    26 00     & . 
    add hl,hl           ;0d40    29     ) 
    add hl,hl           ;0d41    29     ) 
    add hl,hl           ;0d42    29     ) 
    add hl,hl           ;0d43    29     ) 
    ld bc,BUFFER        ;0d44    01 00 5b     . . [ 
    add hl,bc           ;0d47    09     . 
    ret                 ;0d48    c9     . 
    call GET_FNAME      ;0d49    cd f2 2c     . . , 
    call READT0S0       ;0d4c    cd 60 23     . ` # 
    ld b,#80            ;0d4f    06 80     . . 
    ld c,0              ;0d51    0e 00     . . 
    push bc             ;0d53    c5     . 
    call DIRENTRYPOS    ;0d54    cd 3d 2d     . = - 
    call NXTDIRSEC      ;0d57    cd 73 24     . s $ 
    pop bc              ;0d5a    c1     . 
    push bc             ;0d5b    c5     . 
    ld a,c              ;0d5c    79     y 
    cp 16               ;0d5d    fe 10     . . 
    jr nz,$+7           ;0d5f    20 05       . 
    pop bc              ;0d61    c1     . 
    ld c,0              ;0d62    0e 00     . . 
    jr $-17             ;0d64    18 ed     . . 
    ld de,FILENAME      ;0d66    11 dd 5c     . . \ 
    ld a,(CMP_SIZE)     ;0d69    3a 06 5d     : . ] 
    ld b,a              ;0d6c    47     G 
    xor a               ;0d6d    af     . 
    cp (hl)             ;0d6e    be     . 
    jr nz,$+5           ;0d6f    20 03       . 
    pop bc              ;0d71    c1     . 
    jr $+11             ;0d72    18 09     . . 
    call CP_STRING      ;0d74    cd 87 37     . . 7 
    pop bc              ;0d77    c1     . 
    jr z,$+8            ;0d78    28 06     ( . 
    inc c               ;0d7a    0c     . 
    djnz $-40           ;0d7b    10 d6     . . 
    or #FF              ;0d7d    f6 ff     . . 
    ret                 ;0d7f    c9     . 
    ld a,#80            ;0d80    3e 80     > . 
    sub b               ;0d82    90     . 
    ld c,a              ;0d83    4f     O 
    ld (FILEPOS),a      ;0d84    32 1e 5d     2 . ] 
    xor a               ;0d87    af     . 
    ret z               ;0d88    c8     . 
    call SEEKFILE01     ;0d89    cd 4c 2d     . L - 
    ld hl,D_ERRCOD      ;0d8c    21 0f 5d     ! . ] 
    ld (hl),c           ;0d8f    71     q 
    ret z               ;0d90    c8     . 
    ld (hl),#FF         ;0d91    36 ff     6 . 
    ret                 ;0d93    c9     . 
    call SYN_CHCK       ;0d94    cd 0e 2e     . . . 
    call IF1VSWP        ;0d97    cd 8c 31     . . 1 
    res 3,(iy+1)        ;0d9a    fd cb 01 9e     . . . . 
    call RST_ERRSP      ;0d9e    cd d5 21     . . ! 
    ld sp,(OLDSP)       ;0da1    ed 7b 1c 5d     . { . ] 
    ld hl,(ERR_SP)      ;0da5    2a 3d 5c     * = \ 
    dec hl              ;0da8    2b     + 
    ld a,18             ;0da9    3e 12     > . 
    cp (hl)             ;0dab    be     . 
    jr nz,$+6           ;0dac    20 04       . 
    dec hl              ;0dae    2b     + 
    ld (ERR_SP),hl      ;0daf    22 3d 5c     " = \ 
    ret                 ;0db2    c9     . 
    bit 7,(iy+0)        ;0db3    fd cb 00 7e     . . . ~ 
    jr z,$+7            ;0db7    28 05     ( . 
    ld a,11             ;0db9    3e 0b     > . 
    ld (ERR_NR),a       ;0dbb    32 3a 5c     2 : \ 
    inc a               ;0dbe    3c     < 
    ld hl,M_ERROR       ;0dbf    21 57 39     ! W 9 
    call PRINTERR       ;0dc2    cd 42 23     . B # 
    jp DSTM_RET         ;0dc5    c3 70 21     . p ! 
    ld a,(ERR_NR)       ;0dc8    3a 3a 5c     : : \ 
    ld hl,M_BREAK       ;0dcb    21 ad 37     ! . 7 
    cp 20               ;0dce    fe 14     . . 
    jr z,$-14           ;0dd0    28 f0     ( . 
    cp 12               ;0dd2    fe 0c     . . 
    jr z,$-18           ;0dd4    28 ec     ( . 
    ld hl,M_OUT_RAM     ;0dd6    21 b5 37     ! . 7 
    cp 3                ;0dd9    fe 03     . . 
    jr z,$-25           ;0ddb    28 e5     ( . 
    jr $-42             ;0ddd    18 d4     . . 
    call RS_LDEXEC      ;0ddf    cd 81 29     . . ) 
    call FILELOAD       ;0de2    cd 65 29     . e ) 
    call SYN_CHCK       ;0de5    cd 0e 2e     . . . 
    ld hl,(FILEPARM1)   ;0de8    2a e6 5c     * . \ 
    ld a,(FILETYPE)     ;0deb    3a e5 5c     : . \ 
    cp #42              ;0dee    fe 42     . B 
    jp z,EXEC_BAS       ;0df0    ca f1 20     . .   
    push hl             ;0df3    e5     . 
    ld hl,DSTM_RET      ;0df4    21 70 21     ! p ! 
    push hl             ;0df7    e5     . 
    jp CALLBAS1         ;0df8    c3 50 3c     . P < 
    ld hl,CLR_WSP       ;0dfb    21 0e 5d     ! . ] 
    ld a,(hl)           ;0dfe    7e     ~ 
    cp #FF              ;0dff    fe ff     . . 
    ld (hl),0           ;0e01    36 00     6 . 
    ret nz              ;0e03    c0     . 
    ld hl,#16BF         ;0e04    21 bf 16     ! . . 
    jr $+47             ;0e07    18 2d     . - 
    bit 7,(iy+1)        ;0e09    fd cb 01 7e     . . . ~ 
    ret                 ;0e0d    c9     . 
    call B7_FLAGS       ;0e0e    cd 09 2e     . . . 
    ret nz              ;0e11    c0     . 
    pop hl              ;0e12    e1     . 
    ret                 ;0e13    c9     . 
    call BAS_NXTCHR     ;0e14    cd cb 2e     . . . 
    call BAS_E1NUM      ;0e17    cd 5d 2e     . ] . 
    jr $-17             ;0e1a    18 ed     . . 
    xor a               ;0e1c    af     . 
    ld hl,#1601         ;0e1d    21 01 16     ! . . 
    jr $+22             ;0e20    18 14     . . 
    ld a,2              ;0e22    3e 02     > . 
    jr $-7              ;0e24    18 f7     . . 
    ld hl,24            ;0e26    21 18 00     ! . . 
    jr $+13             ;0e29    18 0b     . . 
    call OPEN_K         ;0e2b    cd 1c 2e     . . . 
    ld hl,00f2ch        ;0e2e    21 2c 0f     ! , . 
    jr $+5              ;0e31    18 03     . . 
    ld hl,#0D6B         ;0e33    21 6b 0d     ! k . 
    push hl             ;0e36    e5     . 
    call CALLBAS1       ;0e37    cd 50 3c     . P < 
    ret                 ;0e3a    c9     . 
    ld hl,#28B2         ;0e3b    21 b2 28     ! . ( 
    jr $-8              ;0e3e    18 f6     . . 
    ld hl,#0D6E         ;0e40    21 6e 0d     ! n . 
    jr $-13             ;0e43    18 f1     . . 
    call SAVECFGS       ;0e45    cd 18 39     . . 9 
    ld hl,#1A1B         ;0e48    21 1b 1a     ! . . 
    jp BAS_PRNTBC01     ;0e4b    c3 12 39     . . 9 
    ld hl,#2BF1         ;0e4e    21 f1 2b     ! . + 
    jr $-27             ;0e51    18 e3     . . 
    ld hl,#1E99         ;0e53    21 99 1e     ! . . 
    jr $-32             ;0e56    18 de     . . 
    ld hl,#1C8C         ;0e58    21 8c 1c     ! . . 
    jr $-37             ;0e5b    18 d9     . . 
    ld hl,#1C82         ;0e5d    21 82 1c     ! . . 
    jr $-42             ;0e60    18 d4     . . 
    ld hl,(DSTMADDR)    ;0e62    2a 11 5d     * . ] 
    inc hl              ;0e65    23     # 
    ld (CH_ADD),hl      ;0e66    22 5d 5c     " ] \ 
    ret                 ;0e69    c9     . 
    call GET1ARG_S      ;0e6a    cd 7c 2e     . | . 
    call BAS_GETCHR     ;0e6d    cd 26 2e     . & . 
    cp #2C              ;0e70    fe 2c     . , 
    jp nz,ER_SYNTX      ;0e72    c2 b3 2d     . . - 
    call BAS_NXTCHR     ;0e75    cd cb 2e     . . . 
    call BAS_EEXP       ;0e78    cd 58 2e     . X . 
    ret                 ;0e7b    c9     . 
    call DEFCHADD       ;0e7c    cd 62 2e     . b . 
    jp BAS_EEXP         ;0e7f    c3 58 2e     . X . 
    call BAS_GETCHR     ;0e82    cd 26 2e     . & . 
    cp #AF              ;0e85    fe af     . . 
    ret nz              ;0e87    c0     . 
    call GETARG_N       ;0e88    cd 14 2e     . . . 
    jr z,$+13           ;0e8b    28 0b     ( . 
    call BAS_FDINT      ;0e8d    cd 53 2e     . S . 
    ld (VAR_B_L),bc     ;0e90    ed 43 d9 5c     . C . \ 
    ld (VAR_C_L),bc     ;0e94    ed 43 db 5c     . C . \ 
    call BAS_GETCHR     ;0e98    cd 26 2e     . & . 
    cp #2C              ;0e9b    fe 2c     . , 
    jr z,$+11           ;0e9d    28 09     ( . 
    cp #0D              ;0e9f    fe 0d     . . 
    jp nz,ER_SYNTX      ;0ea1    c2 b3 2d     . . - 
    call SYN_CHCK       ;0ea4    cd 0e 2e     . . . 
    ret                 ;0ea7    c9     . 
    call GETARG_N       ;0ea8    cd 14 2e     . . . 
    ret z               ;0eab    c8     . 
    call BAS_FDINT      ;0eac    cd 53 2e     . S . 
    ld (VAR_C_L),bc     ;0eaf    ed 43 db 5c     . C . \ 
    ld a,3              ;0eb3    3e 03     > . 
    ld (CODEARG),a      ;0eb5    32 d6 5c     2 . \ 
    ret                 ;0eb8    c9     . 
    ld hl,(DSTMADDR)    ;0eb9    2a 11 5d     * . ] 
    rst 32              ;0ebc    e7     . 
    ld hl,#11A7         ;0ebd    21 a7 11     ! . . 
    jr $+15             ;0ec0    18 0d     . . 
    ld hl,(WORKSP)      ;0ec2    2a 61 5c     * a \ 
    rst 32              ;0ec5    e7     . 
    ld hl,#30           ;0ec6    21 30 00     ! 0 . 
    jr $+6              ;0ec9    18 04     . . 
    rst 32              ;0ecb    e7     . 
    ld hl,SAVE_HL       ;0ecc    21 20 00     !   . 
    push hl             ;0ecf    e5     . 
    ld hl,(HLTEMP)      ;0ed0    2a 02 5d     * . ] 
    call CALLBAS1       ;0ed3    cd 50 3c     . P < 
    ret                 ;0ed6    c9     . 
    rst 32              ;0ed7    e7     . 
    ld hl,#19E8         ;0ed8    21 e8 19     ! . . 
    jr $-12             ;0edb    18 f2     . . 
    rst 32              ;0edd    e7     . 
    ld hl,#1655         ;0ede    21 55 16     ! U . 
    jr $-18             ;0ee1    18 ec     . . 
    call READTRACK      ;0ee3    cd 4f 3e     . O > 
    ld a,h              ;0ee6    7c     | 
    out (#3F ),a        ;0ee7    d3 3f     . ? 
    ret                 ;0ee9    c9     . 
    xor a               ;0eea    af     . 
    jr $+38             ;0eeb    18 24     . $ 
    call PUTENTRY       ;0eed    cd bc 27     . . ' 
    ld de,(RWSECID)     ;0ef0    ed 5b f4 5c     . [ . \ 
    dec de              ;0ef4    1b     . 
    ld b,1              ;0ef5    06 01     . . 
    ld hl,BUFFER        ;0ef7    21 00 5b     ! . [ 
    push hl             ;0efa    e5     . 
    push de             ;0efb    d5     . 
    call FT_DSKTYPE     ;0efc    cd ba 3d     . . = 
    bit 7,(hl)          ;0eff    cb 7e     . ~ 
    jr z,$+12           ;0f01    28 0a     ( . 
    bit 0,(hl)          ;0f03    cb 46     . F 
    jr nz,$+8           ;0f05    20 06       . 
    ld hl,M_RDONLY      ;0f07    21 7d 39     ! } 9 
    jp ERROR_RET        ;0f0a    c3 c2 2d     . . - 
    pop de              ;0f0d    d1     . 
    pop hl              ;0f0e    e1     . 
    ld a,#FF            ;0f0f    3e ff     > . 
    ld (FLAGRW),a       ;0f11    32 ce 5c     2 . \ 
    ld (RWSECID),de     ;0f14    ed 53 f4 5c     . S . \ 
    push bc             ;0f18    c5     . 
    push hl             ;0f19    e5     . 
    call CURRTRACK      ;0f1a    cd e3 2e     . . . 
    pop hl              ;0f1d    e1     . 
    pop bc              ;0f1e    c1     . 
    xor a               ;0f1f    af     . 
    or b                ;0f20    b0     . 
    ret z               ;0f21    c8     . 
    push bc             ;0f22    c5     . 
    push hl             ;0f23    e5     . 
    call SAV_RWADD      ;0f24    cd 9f 3e     . . > 
    ld a,(RWSECID)      ;0f27    3a f4 5c     : . \ 
    call SAV_STARTS     ;0f2a    cd 9b 3e     . . > 
    ld a,(RWTRKID)      ;0f2d    3a f5 5c     : . \ 
    call TRACK_LA       ;0f30    cd 0c 3e     . . > 
    ld a,(FLAGRW)       ;0f33    3a ce 5c     : . \ 
    or a                ;0f36    b7     . 
    push af             ;0f37    f5     . 
    call z,READSECTOR   ;0f38    cc a7 3e     . . > 
    pop af              ;0f3b    f1     . 
    call nz,WRITESECTOR ;0f3c    c4 a3 3e     . . > 
    pop hl              ;0f3f    e1     . 
    ld de,256           ;0f40    11 00 01     . . . 
    add hl,de           ;0f43    19     . 
    push hl             ;0f44    e5     . 
    ld a,16             ;0f45    3e 10     > . 
    ld hl,RWSECID       ;0f47    21 f4 5c     ! . \ 
    inc (hl)            ;0f4a    34     4 
    cp (hl)             ;0f4b    be     . 
    jr nz,$+8           ;0f4c    20 06       . 
    ld (hl),0           ;0f4e    36 00     6 . 
    ld hl,RWTRKID       ;0f50    21 f5 5c     ! . \ 
    inc (hl)            ;0f53    34     4 
    pop hl              ;0f54    e1     . 
    pop bc              ;0f55    c1     . 
    djnz $-52           ;0f56    10 ca     . . 
    ret                 ;0f58    c9     . 
    push hl             ;0f59    e5     . 
    ld h,a              ;0f5a    67     g 
    ld l,0              ;0f5b    2e 00     . . 
    push hl             ;0f5d    e5     . 
    sbc hl,de           ;0f5e    ed 52     . R 
    call c,RESCODARG    ;0f60    dc 69 2f     . i / 
    pop hl              ;0f63    e1     . 
    ld a,h              ;0f64    7c     | 
    pop hl              ;0f65    e1     . 
    ret c               ;0f66    d8     . 
    ld a,d              ;0f67    7a     z 
    ret                 ;0f68    c9     . 
    xor a               ;0f69    af     . 
    ld (CODEARG),a      ;0f6a    32 d6 5c     2 . \ 
    scf                 ;0f6d    37     7 
    ret                 ;0f6e    c9     . 
    ld hl,65535         ;0f6f    21 ff ff     ! . . 
    ld (VAR_A_L),hl     ;0f72    22 d7 5c     " . \ 
    ld (VAR_B_L),hl     ;0f75    22 d9 5c     " . \ 
    ld (NODISK),hl      ;0f78    22 d1 5c     " . \ 
    call NOARG          ;0f7b    cd aa 23     . . # 
    jp z,ER_SYNTX       ;0f7e    ca b3 2d     . . - 
    call GET1ARG_S      ;0f81    cd 7c 2e     . | . 
    call SYN_CHCK       ;0f84    cd 0e 2e     . . . 
    call GET_FNAME      ;0f87    cd f2 2c     . . , 
    call FT_DSKTYPE     ;0f8a    cd ba 3d     . . = 
    and #80             ;0f8d    e6 80     . . 
    ld a,#28            ;0f8f    3e 28     > ( 
    jr z,$+4            ;0f91    28 02     ( . 
    ld a,#50            ;0f93    3e 50     > P 
    ld (VAR_A_L),a      ;0f95    32 d7 5c     2 . \ 
    call RESTORE        ;0f98    cd 3d 3d     . = = 
    call SELSIDE1       ;0f9b    cd a3 30     . . 0 
    call LONGDELAY      ;0f9e    cd 3d 3e     . = > 
    ld e,1              ;0fa1    1e 01     . . 
    call FMT_TRK        ;0fa3    cd aa 30     . . 0 
    call SELSIDE0       ;0fa6    cd 98 30     . . 0 
    ld e,0              ;0fa9    1e 00     . . 
    call FMT_TRK        ;0fab    cd aa 30     . . 0 
    ld a,(FILENAME)     ;0fae    3a dd 5c     : . \ 
    cp #24              ;0fb1    fe 24     . $ 
    jr z,$+21           ;0fb3    28 13     ( . 
    call SELSIDE1       ;0fb5    cd a3 30     . . 0 
    call LONGDELAY      ;0fb8    cd 3d 3e     . = > 
    call READTRACK01    ;0fbb    cd 52 3e     . R > 
    ld a,h              ;0fbe    7c     | 
    cp 1                ;0fbf    fe 01     . . 
    jr nz,$+7           ;0fc1    20 05       . 
    ld a,#80            ;0fc3    3e 80     > . 
    ld (VAR_B_H),a      ;0fc5    32 da 5c     2 . \ 
    call FMTDISK        ;0fc8    cd 64 31     . d 1 
    ld hl,BUFFER        ;0fcb    21 00 5b     ! . [ 
    ld (hl),0           ;0fce    36 00     6 . 
    ld de,BUFFER+1      ;0fd0    11 01 5b     . . [ 
    ld bc,255           ;0fd3    01 ff 00     . . . 
    ldir                ;0fd6    ed b0     . . 
    ld bc,VAR_A_L       ;0fd8    01 d7 5c     . . \ 
    ld de,VAR_B_H       ;0fdb    11 da 5c     . . \ 
    ld a,(bc)           ;0fde    0a     . 
    cp #50              ;0fdf    fe 50     . P 
    jr z,$+21           ;0fe1    28 13     ( . 
    ld a,(de)           ;0fe3    1a     . 
    cp #80              ;0fe4    fe 80     . . 
    jr z,$+9            ;0fe6    28 07     ( . 
    ld a,25             ;0fe8    3e 19     > . 
    ld hl,#0270         ;0fea    21 70 02     ! p . 
    jr $+21             ;0fed    18 13     . . 
    ld a,23             ;0fef    3e 17     > . 
    ld hl,#04F0         ;0ff1    21 f0 04     ! . . 
    jr $+14             ;0ff4    18 0c     . . 
    ld a,(de)           ;0ff6    1a     . 
    cp #80              ;0ff7    fe 80     . . 
    ld a,24             ;0ff9    3e 18     > . 
    jr nz,$-10          ;0ffb    20 f4       . 
    ld a,22             ;0ffd    3e 16     > . 
    ld hl,#09F0         ;0fff    21 f0 09     ! . . 
    ld (#5BE3),a        ;1002    32 e3 5b     2 . [ 
    ld (#5BE5),hl       ;1005    22 e5 5b     " . [ 
    ld a,1              ;1008    3e 01     > . 
    ld (#5BE2),a        ;100a    32 e2 5b     2 . [ 
    ld a,16             ;100d    3e 10     > . 
    ld (#5BE7),a        ;100f    32 e7 5b     2 . [ 
    ld hl,#5BEA         ;1012    21 ea 5b     ! . [ 
    ld de,#5BEB         ;1015    11 eb 5b     . . [ 
    ld bc,8             ;1018    01 08 00     . . . 
    ld (hl),32          ;101b    36 20     6   
    ldir                ;101d    ed b0     . . 
    ld hl,FILENAME      ;101f    21 dd 5c     ! . \ 
    ld de,#5BF5         ;1022    11 f5 5b     . . [ 
    ld bc,8             ;1025    01 08 00     . . . 
    ldir                ;1028    ed b0     . . 
    call SELSIDE0       ;102a    cd 98 30     . . 0 
    ld b,1              ;102d    06 01     . . 
    ld de,8             ;102f    11 08 00     . . . 
    ld hl,BUFFER        ;1032    21 00 5b     ! . [ 
    call WRSECTORS02    ;1035    cd 0f 2f     . . / 
    ld a,(CODEARG)      ;1038    3a d6 5c     : . \ 
    push af             ;103b    f5     . 
    xor a               ;103c    af     . 
    ld (FILETYPE),a     ;103d    32 e5 5c     2 . \ 
    ld hl,(#5BE5)       ;1040    2a e5 5b     * . [ 
    ld (VAR_A_L),hl     ;1043    22 d7 5c     " . \ 
    ld hl,FILENAME      ;1046    21 dd 5c     ! . \ 
    rst 24              ;1049    df     . 
    ld a,#0D            ;104a    3e 0d     > . 
    rst 16              ;104c    d7     . 
    ld hl,(VAR_A_L)     ;104d    2a d7 5c     * . \ 
    pop af              ;1050    f1     . 
    push hl             ;1051    e5     . 
    ld d,0              ;1052    16 00     . . 
    ld e,a              ;1054    5f     _ 
    sbc hl,de           ;1055    ed 52     . R 
    ld b,h              ;1057    44     D 
    ld c,l              ;1058    4d     M 
    call BAS_PRNTBC     ;1059    cd 45 2e     . E . 
    ld a,#2F            ;105c    3e 2f     > / 
    rst 16              ;105e    d7     . 
    pop bc              ;105f    c1     . 
    call BAS_PRNTBC     ;1060    cd 45 2e     . E . 
    jp DSTM_RET         ;1063    c3 70 21     . p ! 

;------------------------------------------------------------------------------
; Mirror (#1066/4198) of sector interleaving table (#3066/12390).
;------------------------------------------------------------------------------
    defb 1,9,2,10
    defb 3,11,4,12
    defb 5,13,6,14
    defb 7,15,8,16
    defb 1
;------------------------------------------------------------------------------

    call FT_STEPRT      ;1077    cd b1 3d     . . = 
    or 17               ;107a    f6 11     . . 
    ld b,a              ;107c    47     G 
    ld a,#32            ;107d    3e 32     > 2 
    call SEEK_A         ;107f    cd ed 3d     . . = 
    ld a,2              ;1082    3e 02     > . 
    call SEEK_A         ;1084    cd ed 3d     . . = 
    call DELAY          ;1087    cd a6 3d     . . = 
    in a,(31)           ;108a    db 1f     . . 
    and 4               ;108c    e6 04     . . 
    ld a,#50            ;108e    3e 50     > P 
    jr z,$+4            ;1090    28 02     ( . 
    ld a,#28            ;1092    3e 28     > ( 
    ld (VAR_A_L),a      ;1094    32 d7 5c     2 . \ 
    ret                 ;1097    c9     . 
    ld a,(PORT255)      ;1098    3a 16 5d     : . ] 
    or #3C              ;109b    f6 3c     . < 
    ld (PORT255),a      ;109d    32 16 5d     2 . ] 
    out (255),a         ;10a0    d3 ff     . . 
    ret                 ;10a2    c9     . 
    ld a,(PORT255)      ;10a3    3a 16 5d     : . ] 
    and #6F             ;10a6    e6 6f     . o 
    jr $-11             ;10a8    18 f3     . . 
    ld a,#F4            ;10aa    3e f4     > . 
    out (31),a          ;10ac    d3 1f     . . 
    ld hl,#3066         ;10ae    21 66 30     ! f 0 
    ld c,127            ;10b1    0e 7f     . © 
    ld b,10             ;10b3    06 0a     . . 
    ld d,#4E            ;10b5    16 4e     . N 
    call PUTDATA01      ;10b7    cd 58 31     . X 1 
    ld b,12             ;10ba    06 0c     . . 
    ld d,0              ;10bc    16 00     . . 
    call PUTDATA01      ;10be    cd 58 31     . X 1 
    ld b,3              ;10c1    06 03     . . 
    ld d,#F5            ;10c3    16 f5     . . 
    call PUTDATA01      ;10c5    cd 58 31     . X 1 
    ld d,254            ;10c8    16 fe     . . 
    call PUTDATA        ;10ca    cd 56 31     . V 1 
    ld d,e              ;10cd    53     S 
    call PUTDATA        ;10ce    cd 56 31     . V 1 
    ld d,0              ;10d1    16 00     . . 
    call PUTDATA        ;10d3    cd 56 31     . V 1 
    ld d,(hl)           ;10d6    56     V 
    call PUTDATA        ;10d7    cd 56 31     . V 1 
    ld d,1              ;10da    16 01     . . 
    call PUTDATA        ;10dc    cd 56 31     . V 1 
    ld d,#F7            ;10df    16 f7     . . 
    call PUTDATA        ;10e1    cd 56 31     . V 1 
    ld b,22             ;10e4    06 16     . . 
    ld d,#4E            ;10e6    16 4e     . N 
    call PUTDATA01      ;10e8    cd 58 31     . X 1 
    ld b,12             ;10eb    06 0c     . . 
    ld d,0              ;10ed    16 00     . . 
    call PUTDATA01      ;10ef    cd 58 31     . X 1 
    ld b,3              ;10f2    06 03     . . 
    ld d,#F5            ;10f4    16 f5     . . 
    call PUTDATA01      ;10f6    cd 58 31     . X 1 
    ld d,#FB            ;10f9    16 fb     . . 
    call PUTDATA        ;10fb    cd 56 31     . V 1 
    ld b,0              ;10fe    06 00     . . 
    ld d,0              ;1100    16 00     . . 
    call PUTDATA01      ;1102    cd 58 31     . X 1 
    ld d,#F7            ;1105    16 f7     . . 
    call PUTDATA        ;1107    cd 56 31     . V 1 
    ld b,#32            ;110a    06 32     . 2 
    ld d,#4E            ;110c    16 4e     . N 
    call PUTDATA01      ;110e    cd 58 31     . X 1 
    ld a,(hl)           ;1111    7e     ~ 
    inc hl              ;1112    23     # 
    cp 16               ;1113    fe 10     . . 
    jr nz,$-98          ;1115    20 9c       . 
    ld b,0              ;1117    06 00     . . 
    call PUTDATA01      ;1119    cd 58 31     . X 1 
    jp m,FMT_TRK02      ;111c    fa 22 31     . " 1 
    call PUTDATA01      ;111f    cd 58 31     . X 1 
    in a,(31)           ;1122    db 1f     . . 
    and #40             ;1124    e6 40     . @ 
    jp nz,RDWRSECT03    ;1126    c2 d0 3e     . . > 
    ld a,(VAR_A_H)      ;1129    3a d8 5c     : . \ 
    or a                ;112c    b7     . 
    ret nz              ;112d    c0     . 
    ld a,e              ;112e    7b     { 
    out (#3F ),a        ;112f    d3 3f     . ? 
    ld hl,#3067         ;1131    21 67 30     ! g 0 
    ld b,3              ;1134    06 03     . . 
    ld a,(hl)           ;1136    7e     ~ 
    out (95),a          ;1137    d3 5f     . _ 
    push hl             ;1139    e5     . 
    ld a,#80            ;113a    3e 80     > . 
    out (31),a          ;113c    d3 1f     . . 
    push bc             ;113e    c5     . 
    call FDC_RDATA02    ;113f    cd 7b 3f     . { ? 
    in a,(31)           ;1142    db 1f     . . 
    or a                ;1144    b7     . 
    pop bc              ;1145    c1     . 
    jr z,$+8            ;1146    28 06     ( . 
    djnz $-14           ;1148    10 f0     . . 
    ld hl,CODEARG       ;114a    21 d6 5c     ! . \ 
    inc (hl)            ;114d    34     4 
    pop hl              ;114e    e1     . 
    ld a,(hl)           ;114f    7e     ~ 
    inc hl              ;1150    23     # 
    cp 16               ;1151    fe 10     . . 
    jr nz,$-31          ;1153    20 df       . 
    ret                 ;1155    c9     . 
    ld b,1              ;1156    06 01     . . 
    in a,(255)          ;1158    db ff     . . 
    and #C0             ;115a    e6 c0     . . 
    jr z,$-4            ;115c    28 fa     ( . 
    ret m               ;115e    f8     . 
    out (c),d           ;115f    ed 51     . Q 
    djnz $-9            ;1161    10 f5     . . 
    ret                 ;1163    c9     . 
    ld hl,VAR_A_L       ;1164    21 d7 5c     ! . \ 
    ld b,(hl)           ;1167    46     F 
    xor a               ;1168    af     . 
    inc hl              ;1169    23     # 
    ld (hl),a           ;116a    77     w 
    ld e,#FF            ;116b    1e ff     . . 
    push bc             ;116d    c5     . 
    inc e               ;116e    1c     . 
    ld a,e              ;116f    7b     { 
    ld b,#1B            ;1170    06 1b     . . 
    call SEEK_A         ;1172    cd ed 3d     . . = 
    call SELSIDE0       ;1175    cd 98 30     . . 0 
    call FMT_TRK        ;1178    cd aa 30     . . 0 
    ld a,(VAR_B_H)      ;117b    3a da 5c     : . \ 
    cp #80              ;117e    fe 80     . . 
    jr nz,$+8           ;1180    20 06       . 
    call SELSIDE1       ;1182    cd a3 30     . . 0 
    call FMT_TRK        ;1185    cd aa 30     . . 0 
    pop bc              ;1188    c1     . 
    djnz $-28           ;1189    10 e2     . . 
    ret                 ;118b    c9     . 
    push af             ;118c    f5     . 
    ld a,(CHANSCOPY)    ;118d    3a b6 5c     : . \ 
    cp #F4              ;1190    fe f4     . . 
    jr z,$+27           ;1192    28 19     ( . 
    ld hl,IF1VAR        ;1194    21 18 5d     ! . ] 
    or (hl)             ;1197    b6     . 
    ld (hl),#FF         ;1198    36 ff     6 . 
    jr z,$+19           ;119a    28 11     ( . 
    ld hl,#5CC3         ;119c    21 c3 5c     ! . \ 
    ld de,#5D33         ;119f    11 33 5d     . 3 ] 
    ld b,#2D            ;11a2    06 2d     . - 
    ld c,(hl)           ;11a4    4e     N 
    ld a,(de)           ;11a5    1a     . 
    ld (hl),a           ;11a6    77     w 
    ld a,c              ;11a7    79     y 
    ld (de),a           ;11a8    12     . 
    inc hl              ;11a9    23     # 
    inc de              ;11aa    13     . 
    djnz $-7            ;11ab    10 f7     . . 
    pop af              ;11ad    f1     . 
    ret                 ;11ae    c9     . 
    ld hl,(E_LINE)      ;11af    2a 59 5c     * Y \ 
    ld (hl),#0D         ;11b2    36 0d     6 . 
    ld (K_CUR),hl       ;11b4    22 5b 5c     " [ \ 
    inc hl              ;11b7    23     # 
    ld (hl),#80         ;11b8    36 80     6 . 
    ret                 ;11ba    c9     . 
    ld de,(E_LINE)      ;11bb    ed 5b 59 5c     . [ Y \ 
    ld hl,ELINE_T       ;11bf    21 20 5d     !   ] 
    call COPY3B         ;11c2    cd 42 22     . B " 
    ret                 ;11c5    c9     . 
    ld a,(D_ERRCOD)     ;11c6    3a 0f 5d     : . ] 
    or a                ;11c9    b7     . 
    push af             ;11ca    f5     . 
    call nz,LOADLINE    ;11cb    c4 bb 31     . . 1 
    pop af              ;11ce    f1     . 
    call z,CLEARLINE    ;11cf    cc af 31     . . 1 
    ld hl,(E_LINE)      ;11d2    2a 59 5c     * Y \ 
    call PRT_ENTER      ;11d5    cd 1f 3d     . . = 
    ld a,(DEFLTDRV)     ;11d8    3a 19 5d     : . ] 
    add a,#41           ;11db    c6 41     . A 
    rst 16              ;11dd    d7     . 
    ld a,#3E            ;11de    3e 3e     > > 
    rst 16              ;11e0    d7     . 
    ld hl,ERR_NR        ;11e1    21 3a 5c     ! : \ 
    ld (hl),#FF         ;11e4    36 ff     6 . 
    jp BAS_EDITOR       ;11e6    c3 2b 2e     . + . 
    call BAS_NXTCHR     ;11e9    cd cb 2e     . . . 
    call BAS_GETCHR     ;11ec    cd 26 2e     . & . 
    cp #2C              ;11ef    fe 2c     . , 
    jp nz,ER_SYNTX      ;11f1    c2 b3 2d     . . - 
    ld hl,(VAR_C_L)     ;11f4    2a db 5c     * . \ 
    ld (VAR_B_L),hl     ;11f7    22 d9 5c     " . \ 
    call GETARG_I       ;11fa    cd a8 2e     . . . 
    call SYN_CHCK       ;11fd    cd 0e 2e     . . . 
    ld hl,(VAR_C_L)     ;1200    2a db 5c     * . \ 
    ld a,h              ;1203    7c     | 
    or a                ;1204    b7     . 
    jp nz,ER_SYNTX      ;1205    c2 b3 2d     . . - 
    inc hl              ;1208    23     # 
    ld (VAR_A_L),hl     ;1209    22 d7 5c     " . \ 
    ld hl,(VAR_B_L)     ;120c    2a d9 5c     * . \ 
    ld (VAR_C_L),hl     ;120f    22 db 5c     " . \ 
    ret                 ;1212    c9     . 
    ld hl,(DSTMADDR)    ;1213    2a 11 5d     * . ] 
    ld (CH_ADD),hl      ;1216    22 5d 5c     " ] \ 
    call GETARG_I       ;1219    cd a8 2e     . . . 
    call GETARG_CS      ;121c    cd 6d 2e     . m . 
    call BAS_GETCHR     ;121f    cd 26 2e     . & . 
    cp #41              ;1222    fe 41     . A 
    jr nc,$+7           ;1224    30 05     0 . 
    call BAS_NXTCHR     ;1226    cd cb 2e     . . . 
    jr $-10             ;1229    18 f4     . . 
    cp #A5              ;122b    fe a5     . . 
    push af             ;122d    f5     . 
    call z,RND_ARG      ;122e    cc e9 31     . . 1 
    pop af              ;1231    f1     . 
    jr z,$+13           ;1232    28 0b     ( . 
    and #DF             ;1234    e6 df     . . 
    cp #52              ;1236    fe 52     . R 
    jr z,$+7            ;1238    28 05     ( . 
    cp #57              ;123a    fe 57     . W 
    jp nz,ER_SYNTX      ;123c    c2 b3 2d     . . - 
    ld (OPENMODE),a     ;123f    32 09 5d     2 . ] 
    call SYN_CHCK       ;1242    cd 0e 2e     . . . 
    ld a,#23            ;1245    3e 23     > # 
    ld (FILETYPE),a     ;1247    32 e5 5c     2 . \ 
    ld a,0              ;124a    3e 00     > . 
    ld (FILEPARM1),a    ;124c    32 e6 5c     2 . \ 
    call SEEKSTRM       ;124f    cd 6c 32     . l 2 
    push af             ;1252    f5     . 
    call VRF_STRM       ;1253    cd a0 32     . . 2 
    pop af              ;1256    f1     . 
    push af             ;1257    f5     . 
    call nz,NEWSTRM     ;1258    c4 1c 33     . . 3 
    pop af              ;125b    f1     . 
    call INITSTREAM     ;125c    cd d6 32     . . 2 
    ld hl,(DSTMADDR)    ;125f    2a 11 5d     * . ] 
    ld bc,#0124         ;1262    01 24 01     . $ . 
    add hl,bc           ;1265    09     . 
    ld (DSTMADDR),hl    ;1266    22 11 5d     " . ] 
    jp DSTM_RET         ;1269    c3 70 21     . p ! 
    ld a,10             ;126c    3e 0a     > . 
    ld (CMP_SIZE),a     ;126e    32 06 5d     2 . ] 
    call SEEKFILE       ;1271    cd 49 2d     . I - 
    push af             ;1274    f5     . 
    call ID_TYPE        ;1275    cd 84 23     . . # 
    pop af              ;1278    f1     . 
    jr nz,$+30          ;1279    20 1c       . 
    ld a,(OPENMODE)     ;127b    3a 09 5d     : . ] 
    cp #52              ;127e    fe 52     . R 
    jr z,$+18           ;1280    28 10     ( . 
    ld hl,FILEPARM1     ;1282    21 e6 5c     ! . \ 
    inc (hl)            ;1285    34     4 
    call SEEKFILE01     ;1286    cd 4c 2d     . L - 
    jr z,$-7            ;1289    28 f7     ( . 
    ld hl,FILEPARM1     ;128b    21 e6 5c     ! . \ 
    dec (hl)            ;128e    35     5 
    call SEEKFILE01     ;128f    cd 4c 2d     . L - 
    call GETENTRY       ;1292    cd ae 27     . . ' 
    xor a               ;1295    af     . 
    ret                 ;1296    c9     . 
    ld a,(OPENMODE)     ;1297    3a 09 5d     : . ] 
    cp #52              ;129a    fe 52     . R 
    ret nz              ;129c    c0     . 
    jp ER_NOFILE        ;129d    c3 58 23     . X # 
    ld a,(VAR_C_L)      ;12a0    3a db 5c     : . \ 
    ld hl,#1727         ;12a3    21 27 17     ! ' . 
    call CALLBAS        ;12a6    cd 36 2e     . 6 . 
    ld a,b              ;12a9    78     x 
    or c                ;12aa    b1     . 
    jp nz,ER_STMOPEN    ;12ab    c2 af 32     . . 2 
    ret                 ;12ae    c9     . 
    ld a,25             ;12af    3e 19     > . 
    ld (ERR_NR),a       ;12b1    32 3a 5c     2 : \ 
    ld hl,M_STMOPEN     ;12b4    21 d7 37     ! . 7 
    ld a,10             ;12b7    3e 0a     > . 
    jp DSTM_ERRET       ;12b9    c3 e5 2c     . . , 
    ld a,11             ;12bc    3e 0b     > . 
    ld hl,M_NODFILE     ;12be    21 e5 37     ! . 7 
    jr $-8              ;12c1    18 f6     . . 
    push hl             ;12c3    e5     . 
    ld c,32             ;12c4    0e 20     .   
    rst 40              ;12c6    ef     . 
    ld a,(VAR_A_L)      ;12c7    3a d7 5c     : . \ 
    ld (hl),a           ;12ca    77     w 
    inc hl              ;12cb    23     # 
    xor a               ;12cc    af     . 
    ld (hl),a           ;12cd    77     w 
    inc hl              ;12ce    23     # 
    ld (hl),a           ;12cf    77     w 
    inc hl              ;12d0    23     # 
    ld (hl),a           ;12d1    77     w 
    ld a,127            ;12d2    3e 7f     > © 
    pop hl              ;12d4    e1     . 
    ret                 ;12d5    c9     . 
    push af             ;12d6    f5     . 
    call VRF_STRM       ;12d7    cd a0 32     . . 2 
    ex de,hl            ;12da    eb     . 
    ld hl,(PROG)        ;12db    2a 53 5c     * S \ 
    ld bc,(CHANS)       ;12de    ed 4b 4f 5c     . K O \ 
    sbc hl,bc           ;12e2    ed 42     . B 
    ex de,hl            ;12e4    eb     . 
    ld (hl),e           ;12e5    73     s 
    inc hl              ;12e6    23     # 
    ld (hl),d           ;12e7    72     r 
    call MKNEWCHAN      ;12e8    cd 46 33     . F 3 
    ld a,(OPENMODE)     ;12eb    3a 09 5d     : . ] 
    cp #A5              ;12ee    fe a5     . . 
    call z,INIT_RND     ;12f0    cc c3 32     . . 2 
    jr z,$+12           ;12f3    28 0a     ( . 
    ld a,(OPENMODE)     ;12f5    3a 09 5d     : . ] 
    cp #52              ;12f8    fe 52     . R 
    ld a,#FF            ;12fa    3e ff     > . 
    jr nz,$+3           ;12fc    20 01       . 
    xor a               ;12fe    af     . 
    ld (hl),a           ;12ff    77     w 
    pop af              ;1300    f1     . 
    jp INITSTREAM02     ;1301    c3 04 33     . . 3 
    push af             ;1304    f5     . 
    ld bc,20            ;1305    01 14 00     . . . 
    add hl,bc           ;1308    09     . 
    push hl             ;1309    e5     . 
    call CURSSECT       ;130a    cd b4 34     . . 4 
    pop hl              ;130d    e1     . 
    inc hl              ;130e    23     # 
    ld b,1              ;130f    06 01     . . 
    pop af              ;1311    f1     . 
    or a                ;1312    b7     . 
    push af             ;1313    f5     . 
    call nz,WRSECTORS   ;1314    c4 fa 2e     . . . 
    pop af              ;1317    f1     . 
    call z,RDSECTORS    ;1318    cc ea 2e     . . . 
    ret                 ;131b    c9     . 
    ld hl,(VAR_A_L)     ;131c    2a d7 5c     * . \ 
    push hl             ;131f    e5     . 
    ld hl,#2000         ;1320    21 00 20     ! .   
    ld (VAR_A_L),hl     ;1323    22 d7 5c     " . \ 
    call SV_SGMT        ;1326    cd 2e 33     . . 3 
    pop hl              ;1329    e1     . 
    ld (VAR_A_L),hl     ;132a    22 d7 5c     " . \ 
    ret                 ;132d    c9     . 
    ld hl,#1000         ;132e    21 00 10     ! . . 
    ld (VAR_B_L),hl     ;1331    22 d9 5c     " . \ 
    call DIRFULL        ;1334    cd 6e 2b     . n + 
    call SAVEFILE       ;1337    cd 03 2c     . . , 
    ld hl,0             ;133a    21 00 00     ! . . 
    ld (FILEPARM2),hl   ;133d    22 e8 5c     " . \ 
    call PUTENTRY       ;1340    cd bc 27     . . ' 
    jp WRT_BUFFER       ;1343    c3 f0 2e     . . . 
    ld hl,(PROG)        ;1346    2a 53 5c     * S \ 
    dec hl              ;1349    2b     + 
    ld (CURCHL),hl      ;134a    22 51 5c     " Q \ 
    push hl             ;134d    e5     . 
    ld bc,#0124         ;134e    01 24 01     . $ . 
    call BAS_MKROOM     ;1351    cd dd 2e     . . . 
    ld a,0              ;1354    3e 00     > . 
    ld b,0              ;1356    06 00     . . 
    ld (de),a           ;1358    12     . 
    dec de              ;1359    1b     . 
    djnz $-2            ;135a    10 fc     . . 
    pop hl              ;135c    e1     . 
    push hl             ;135d    e5     . 
    ld de,CH_OUTPUT     ;135e    11 0f 3c     . . < 
    ld (hl),e           ;1361    73     s 
    inc hl              ;1362    23     # 
    ld (hl),d           ;1363    72     r 
    inc hl              ;1364    23     # 
    ld de,CH_INPUT      ;1365    11 09 3c     . . < 
    ld (hl),e           ;1368    73     s 
    inc hl              ;1369    23     # 
    ld (hl),d           ;136a    72     r 
    inc hl              ;136b    23     # 
    ld (hl),#44         ;136c    36 44     6 D 
    inc hl              ;136e    23     # 
    inc hl              ;136f    23     # 
    inc hl              ;1370    23     # 
    inc hl              ;1371    23     # 
    inc hl              ;1372    23     # 
    ld (hl),#24         ;1373    36 24     6 $ 
    inc hl              ;1375    23     # 
    ld (hl),1           ;1376    36 01     6 . 
    inc hl              ;1378    23     # 
    ld a,(CURRDRIVE)    ;1379    3a f6 5c     : . \ 
    ld (hl),a           ;137c    77     w 
    inc hl              ;137d    23     # 
    ld a,(FILEPOS)      ;137e    3a 1e 5d     : . ] 
    ld (hl),a           ;1381    77     w 
    inc hl              ;1382    23     # 
    ld a,(OPENMODE)     ;1383    3a 09 5d     : . ] 
    cp #52              ;1386    fe 52     . R 
    ld (hl),0           ;1388    36 00     6 . 
    jr z,$+6            ;138a    28 04     ( . 
    ld a,(FILEPARM2)    ;138c    3a e8 5c     : . \ 
    ld (hl),a           ;138f    77     w 
    inc hl              ;1390    23     # 
    ld (hl),b           ;1391    70     p 
    jr z,$+6            ;1392    28 04     ( . 
    ld a,(FILEPARM2+1)  ;1394    3a e9 5c     : . \ 
    ld (hl),a           ;1397    77     w 
    inc hl              ;1398    23     # 
    ex de,hl            ;1399    eb     . 
    pop hl              ;139a    e1     . 
    push de             ;139b    d5     . 
    ld de,16            ;139c    11 10 00     . . . 
    add hl,de           ;139f    19     . 
    ex de,hl            ;13a0    eb     . 
    ld hl,FILENAME      ;13a1    21 dd 5c     ! . \ 
    ld bc,16            ;13a4    01 10 00     . . . 
    ldir                ;13a7    ed b0     . . 
    pop hl              ;13a9    e1     . 
    ret                 ;13aa    c9     . 
    ld c,#0D            ;13ab    0e 0d     . . 
    rst 40              ;13ad    ef     . 
    ld c,(hl)           ;13ae    4e     N 
    rst 40              ;13af    ef     . 
    ld bc,#24           ;13b0    01 24 00     . $ . 
    add hl,bc           ;13b3    09     . 
    ret                 ;13b4    c9     . 
    ld c,#24            ;13b5    0e 24     . $ 
    ld b,0              ;13b7    06 00     . . 
    ld hl,(CURCHL)      ;13b9    2a 51 5c     * Q \ 
    add hl,bc           ;13bc    09     . 
    ret                 ;13bd    c9     . 
    ld c,#0D            ;13be    0e 0d     . . 
    rst 40              ;13c0    ef     . 
    inc (hl)            ;13c1    34     4 
    ret nz              ;13c2    c0     . 
    push hl             ;13c3    e5     . 
    call STREAMDRV      ;13c4    cd d4 34     . . 4 
    call WR_CHBUFF      ;13c7    cd 8d 34     . . 4 
    pop hl              ;13ca    e1     . 
    inc hl              ;13cb    23     # 
    inc (hl)            ;13cc    34     4 
    push hl             ;13cd    e5     . 
    call RD_CHBUFF      ;13ce    cd a9 34     . . 4 
    pop hl              ;13d1    e1     . 
    ld a,16             ;13d2    3e 10     > . 
    cp (hl)             ;13d4    be     . 
    ret nz              ;13d5    c0     . 
    push hl             ;13d6    e5     . 
    ld c,15             ;13d7    0e 0f     . . 
    rst 40              ;13d9    ef     . 
    ld a,(hl)           ;13da    7e     ~ 
    cp 127              ;13db    fe 7f     . © 
    jr z,$+15           ;13dd    28 0d     ( . 
    ld hl,(CURCHL)      ;13df    2a 51 5c     * Q \ 
    call WR_STMFENT     ;13e2    cd 55 37     . U 7 
    call LOADBUFF       ;13e5    cd 96 3f     . . ? 
    pop hl              ;13e8    e1     . 
    jp NEWSEGMT01       ;13e9    c3 0d 34     . . 4 
    pop hl              ;13ec    e1     . 
    push hl             ;13ed    e5     . 
    call SEEKNXTSEG     ;13ee    cd 5d 34     . ] 4 
    push af             ;13f1    f5     . 
    call z,RD_CHBUFF    ;13f2    cc a9 34     . . 4 
    pop af              ;13f5    f1     . 
    pop hl              ;13f6    e1     . 
    call nz,NEWSEGMT    ;13f7    c4 04 34     . . 4 
    ret                 ;13fa    c9     . 
    ld (hl),0           ;13fb    36 00     6 . 
    ld c,25             ;13fd    0e 19     . . 
    rst 40              ;13ff    ef     . 
    ld d,32             ;1400    16 20     .   
    ld e,(hl)           ;1402    5e     ^ 
    ret                 ;1403    c9     . 
    call GETSEGMT       ;1404    cd fb 33     . . 3 
    ld (VAR_A_L),de     ;1407    ed 53 d7 5c     . S . \ 
    jr $+10             ;140b    18 08     . . 
    call GETSEGMT       ;140d    cd fb 33     . . 3 
    inc e               ;1410    1c     . 
    ld (VAR_A_L),de     ;1411    ed 53 d7 5c     . S . \ 
    call SV_SGMT        ;1415    cd 2e 33     . . 3 
    ld c,16             ;1418    0e 10     . . 
    rst 40              ;141a    ef     . 
    ex de,hl            ;141b    eb     . 
    ld hl,FILENAME      ;141c    21 dd 5c     ! . \ 
    ld bc,16            ;141f    01 10 00     . . . 
    ldir                ;1422    ed b0     . . 
    ld c,12             ;1424    0e 0c     . . 
    rst 40              ;1426    ef     . 
    ld a,(FILEPOS)      ;1427    3a 1e 5d     : . ] 
    ld (hl),a           ;142a    77     w 
    jp LOADBUFF         ;142b    c3 96 3f     . . ? 
    ld c,#0D            ;142e    0e 0d     . . 
    rst 40              ;1430    ef     . 
    inc (hl)            ;1431    34     4 
    ret nz              ;1432    c0     . 
    inc hl              ;1433    23     # 
    inc (hl)            ;1434    34     4 
    push hl             ;1435    e5     . 
    call STREAMDRV      ;1436    cd d4 34     . . 4 
    ld c,#23            ;1439    0e 23     . # 
    rst 40              ;143b    ef     . 
    ld a,(hl)           ;143c    7e     ~ 
    or a                ;143d    b7     . 
    jr z,$+11           ;143e    28 09     ( . 
    pop hl              ;1440    e1     . 
    push hl             ;1441    e5     . 
    dec (hl)            ;1442    35     5 
    call WR_CHBUFF      ;1443    cd 8d 34     . . 4 
    pop hl              ;1446    e1     . 
    push hl             ;1447    e5     . 
    inc (hl)            ;1448    34     4 
    call RD_CHBUFF      ;1449    cd a9 34     . . 4 
    pop hl              ;144c    e1     . 
    ld a,16             ;144d    3e 10     > . 
    cp (hl)             ;144f    be     . 
    call z,NEXTSEGMT    ;1450    cc 54 34     . T 4 
    ret                 ;1453    c9     . 
    call SEEKNXTSEG     ;1454    cd 5d 34     . ] 4 
    jp nz,ER_ENDFILE    ;1457    c2 20 35     .   5 
    jp RD_CHBUFF        ;145a    c3 a9 34     . . 4 
    ld (hl),0           ;145d    36 00     6 . 
    ld c,25             ;145f    0e 19     . . 
    rst 40              ;1461    ef     . 
    inc (hl)            ;1462    34     4 
    ld c,16             ;1463    0e 10     . . 
    rst 40              ;1465    ef     . 
    ld de,FILENAME      ;1466    11 dd 5c     . . \ 
    ld bc,16            ;1469    01 10 00     . . . 
    ldir                ;146c    ed b0     . . 
    call SEEKFILE01     ;146e    cd 4c 2d     . L - 
    ret nz              ;1471    c0     . 
    call GETENTRY       ;1472    cd ae 27     . . ' 
    call LOADBUFF       ;1475    cd 96 3f     . . ? 
    ld c,16             ;1478    0e 10     . . 
    rst 40              ;147a    ef     . 
    ex de,hl            ;147b    eb     . 
    ld hl,FILENAME      ;147c    21 dd 5c     ! . \ 
    ld bc,16            ;147f    01 10 00     . . . 
    ldir                ;1482    ed b0     . . 
    ld c,12             ;1484    0e 0c     . . 
    rst 40              ;1486    ef     . 
    ld a,(FILEPOS)      ;1487    3a 1e 5d     : . ] 
    ld (hl),a           ;148a    77     w 
    xor a               ;148b    af     . 
    ret                 ;148c    c9     . 
    call CURSSECT       ;148d    cd b4 34     . . 4 
    call CHANBUFF       ;1490    cd b5 33     . . 3 
    ld b,1              ;1493    06 01     . . 
    call WRSECTORS      ;1495    cd fa 2e     . . . 
    ld c,15             ;1498    0e 0f     . . 
    rst 40              ;149a    ef     . 
    ld a,(hl)           ;149b    7e     ~ 
    cp 127              ;149c    fe 7f     . © 
    ret z               ;149e    c8     . 
    call CHANBUFF       ;149f    cd b5 33     . . 3 
    xor a               ;14a2    af     . 
    ld b,a              ;14a3    47     G 
    ld (hl),a           ;14a4    77     w 
    inc hl              ;14a5    23     # 
    djnz $-2            ;14a6    10 fc     . . 
    ret                 ;14a8    c9     . 
    call CURSSECT       ;14a9    cd b4 34     . . 4 
    call CHANBUFF       ;14ac    cd b5 33     . . 3 
    ld b,1              ;14af    06 01     . . 
    jp RDSECTORS        ;14b1    c3 ea 2e     . . . 
    ld hl,(CURCHL)      ;14b4    2a 51 5c     * Q \ 
    ld bc,#001E         ;14b7    01 1e 00     . . . 
    add hl,bc           ;14ba    09     . 
    ld e,(hl)           ;14bb    5e     ^ 
    inc hl              ;14bc    23     # 
    ld d,(hl)           ;14bd    56     V 
    ld c,14             ;14be    0e 0e     . . 
    rst 40              ;14c0    ef     . 
    ld b,(hl)           ;14c1    46     F 
    dec b               ;14c2    05     . 
    inc b               ;14c3    04     . 
    push af             ;14c4    f5     . 
    ld a,16             ;14c5    3e 10     > . 
    jr z,$+11           ;14c7    28 09     ( . 
    inc e               ;14c9    1c     . 
    cp e                ;14ca    bb     . 
    jr nz,$+5           ;14cb    20 03       . 
    ld e,0              ;14cd    1e 00     . . 
    inc d               ;14cf    14     . 
    djnz $-7            ;14d0    10 f7     . . 
    pop af              ;14d2    f1     . 
    ret                 ;14d3    c9     . 
    ld c,11             ;14d4    0e 0b     . . 
    rst 40              ;14d6    ef     . 
    ld a,(hl)           ;14d7    7e     ~ 
    jp SEL_DRIVE01      ;14d8    c3 74 3d     . t = 
    push hl             ;14db    e5     . 
    ld hl,IF1VSWP       ;14dc    21 8c 31     ! . 1 
    push hl             ;14df    e5     . 
    push af             ;14e0    f5     . 
    call IF1VSWP        ;14e1    cd 8c 31     . . 1 
    ld a,10             ;14e4    3e 0a     > . 
    ld (CMP_SIZE),a     ;14e6    32 06 5d     2 . ] 
    pop af              ;14e9    f1     . 
    call CHOUT_RND      ;14ea    cd 32 35     . 2 5 
    push af             ;14ed    f5     . 
    call READMODE       ;14ee    cd c1 36     . . 6 
    jp z,ER_INVSTM      ;14f1    ca 2e 35     . . 5 
    pop af              ;14f4    f1     . 
    call CHBUFFADD      ;14f5    cd ab 33     . . 3 
    ld (hl),a           ;14f8    77     w 
    jp CH_OUT02         ;14f9    c3 be 33     . . 3 
    ld c,#0D            ;14fc    0e 0d     . . 
    rst 40              ;14fe    ef     . 
    ld a,(hl)           ;14ff    7e     ~ 
    ld bc,14            ;1500    01 0e 00     . . . 
    add hl,bc           ;1503    09     . 
    cp (hl)             ;1504    be     . 
    ret nz              ;1505    c0     . 
    ld c,14             ;1506    0e 0e     . . 
    rst 40              ;1508    ef     . 
    ld a,(hl)           ;1509    7e     ~ 
    ld bc,14            ;150a    01 0e 00     . . . 
    add hl,bc           ;150d    09     . 
    cp (hl)             ;150e    be     . 
    ret nz              ;150f    c0     . 
    ld hl,CHANSCOPY     ;1510    21 b6 5c     ! . \ 
    ld a,(hl)           ;1513    7e     ~ 
    cp #F4              ;1514    fe f4     . . 
    jr z,$+10           ;1516    28 08     ( . 
    bit 4,(hl)          ;1518    cb 66     . f 
    jr z,$+6            ;151a    28 04     ( . 
    or 1                ;151c    f6 01     . . 
    pop hl              ;151e    e1     . 
    ret                 ;151f    c9     . 
    ld a,#07            ;1520    3e 07     > . 
    ld (ERR_NR),a       ;1522    32 3a 5c     2 : \ 
    call IF1VSWP        ;1525    cd 8c 31     . . 1 
    ld hl,#58           ;1528    21 58 00     ! X . 
    jp CALLBAS          ;152b    c3 36 2e     . 6 . 
    ld a,23             ;152e    3e 17     > . 
    jr $-14             ;1530    18 f0     . . 
    ld d,a              ;1532    57     W 
    ld c,15             ;1533    0e 0f     . . 
    rst 40              ;1535    ef     . 
    ld a,(hl)           ;1536    7e     ~ 
    cp 127              ;1537    fe 7f     . © 
    ld a,d              ;1539    7a     z 
    ret nz              ;153a    c0     . 
    ld bc,19            ;153b    01 13 00     . . . 
    add hl,bc           ;153e    09     . 
    ld a,(hl)           ;153f    7e     ~ 
    or a                ;1540    b7     . 
    ld a,d              ;1541    7a     z 
    jr nz,$+35          ;1542    20 21       ! 
    dec hl              ;1544    2b     + 
    ld a,(hl)           ;1545    7e     ~ 
    or a                ;1546    b7     . 
    jr nz,$+11          ;1547    20 09       . 
    push bc             ;1549    c5     . 
    push hl             ;154a    e5     . 
    push de             ;154b    d5     . 
    call MK16BYTES      ;154c    cd 88 35     . . 5 
    pop de              ;154f    d1     . 
    pop hl              ;1550    e1     . 
    pop bc              ;1551    c1     . 
    ld c,(hl)           ;1552    4e     N 
    ld a,d              ;1553    7a     z 
    ex de,hl            ;1554    eb     . 
    ld hl,(WKSPADD)     ;1555    2a cf 5c     * . \ 
    add hl,bc           ;1558    09     . 
    cp 6                ;1559    fe 06     . . 
    ld (hl),a           ;155b    77     w 
    push de             ;155c    d5     . 
    call z,GETRECORD    ;155d    cc 94 35     . . 5 
    pop de              ;1560    d1     . 
    ex de,hl            ;1561    eb     . 
    inc (hl)            ;1562    34     4 
    pop hl              ;1563    e1     . 
    ret                 ;1564    c9     . 
    dec hl              ;1565    2b     + 
    ld a,(hl)           ;1566    7e     ~ 
    dec hl              ;1567    2b     + 
    inc a               ;1568    3c     < 
    cp (hl)             ;1569    be     . 
    inc hl              ;156a    23     # 
    inc (hl)            ;156b    34     4 
    push hl             ;156c    e5     . 
    push af             ;156d    f5     . 
    ld c,#23            ;156e    0e 23     . # 
    rst 40              ;1570    ef     . 
    ld (hl),#FF         ;1571    36 ff     6 . 
    pop af              ;1573    f1     . 
    pop hl              ;1574    e1     . 
    jr c,$+9            ;1575    38 07     8 . 
    ld a,d              ;1577    7a     z 
    cp #0D              ;1578    fe 0d     . . 
    jr z,$+8            ;157a    28 06     ( . 
    pop bc              ;157c    c1     . 
    ret                 ;157d    c9     . 
    ld a,d              ;157e    7a     z 
    cp #0D              ;157f    fe 0d     . . 
    ret nz              ;1581    c0     . 
    xor a               ;1582    af     . 
    ld (hl),a           ;1583    77     w 
    inc hl              ;1584    23     # 
    ld (hl),a           ;1585    77     w 
    ld a,d              ;1586    7a     z 
    ret                 ;1587    c9     . 
    ld hl,(WORKSP)      ;1588    2a 61 5c     * a \ 
    ld (WKSPADD),hl     ;158b    22 cf 5c     " . \ 
    ld bc,16            ;158e    01 10 00     . . . 
    jp BAS_BCSPC        ;1591    c3 c2 2e     . . . 
    ld (hl),#0D         ;1594    36 0d     6 . 
    ld hl,(CH_ADD)      ;1596    2a 5d 5c     * ] \ 
    ld (VAR_A_L),hl     ;1599    22 d7 5c     " . \ 
    ld hl,(WKSPADD)     ;159c    2a cf 5c     * . \ 
    ld (CH_ADD),hl      ;159f    22 5d 5c     " ] \ 
    ld hl,FLAGS         ;15a2    21 3b 5c     ! ; \ 
    res 7,(hl)          ;15a5    cb be     . . 
    call BAS_E1NUM      ;15a7    cd 5d 2e     . ] . 
    ld hl,FLAGS         ;15aa    21 3b 5c     ! ; \ 
    set 7,(hl)          ;15ad    cb fe     . . 
    ld hl,(WKSPADD)     ;15af    2a cf 5c     * . \ 
    ld (CH_ADD),hl      ;15b2    22 5d 5c     " ] \ 
    call BAS_E1NUM      ;15b5    cd 5d 2e     . ] . 
    call BAS_FDINT      ;15b8    cd 53 2e     . S . 
    push bc             ;15bb    c5     . 
    pop de              ;15bc    d1     . 
    ld c,32             ;15bd    0e 20     .   
    rst 40              ;15bf    ef     . 
    ld b,(hl)           ;15c0    46     F 
    xor a               ;15c1    af     . 
    ld hl,0             ;15c2    21 00 00     ! . . 
    ld (VAR_C_L),hl     ;15c5    22 db 5c     " . \ 
    add hl,de           ;15c8    19     . 
    jr nc,$+11          ;15c9    30 09     0 . 
    push hl             ;15cb    e5     . 
    ld hl,(VAR_C_L)     ;15cc    2a db 5c     * . \ 
    inc hl              ;15cf    23     # 
    ld (VAR_C_L),hl     ;15d0    22 db 5c     " . \ 
    pop hl              ;15d3    e1     . 
    djnz $-12           ;15d4    10 f2     . . 
    ld (VAR_B_L),hl     ;15d6    22 d9 5c     " . \ 
    ld a,(VAR_C_L)      ;15d9    3a db 5c     : . \ 
    ld hl,VAR_B_H       ;15dc    21 da 5c     ! . \ 
    rrd                 ;15df    ed 67     . g 
    and 15              ;15e1    e6 0f     . . 
    ld (VAR_C_L),a      ;15e3    32 db 5c     2 . \ 
    ld hl,(VAR_A_L)     ;15e6    2a d7 5c     * . \ 
    ld (CH_ADD),hl      ;15e9    22 5d 5c     " ] \ 
    call RNDRECORD      ;15ec    cd f8 35     . . 5 
    ld c,#21            ;15ef    0e 21     . ! 
    rst 40              ;15f1    ef     . 
    ld a,#FF            ;15f2    3e ff     > . 
    ld (hl),a           ;15f4    77     w 
    inc hl              ;15f5    23     # 
    ld (hl),a           ;15f6    77     w 
    ret                 ;15f7    c9     . 
    ld hl,(CURCHL)      ;15f8    2a 51 5c     * Q \ 
    push hl             ;15fb    e5     . 
    ld bc,#19           ;15fc    01 19 00     . . . 
    add hl,bc           ;15ff    09     . 
    ld a,(VAR_B_H)      ;1600    3a da 5c     : . \ 
    cp (hl)             ;1603    be     . 
    jp nz,RNDRECORD02   ;1604    c2 1b 36     . . 6 
    pop hl              ;1607    e1     . 
    ld bc,14            ;1608    01 0e 00     . . . 
    add hl,bc           ;160b    09     . 
    ld a,(VAR_C_L)      ;160c    3a db 5c     : . \ 
    cp (hl)             ;160f    be     . 
    jp nz,RNDRECORD03   ;1610    c2 43 36     . C 6 
    ld c,#0D            ;1613    0e 0d     . . 
    rst 40              ;1615    ef     . 
    ld a,(VAR_B_L)      ;1616    3a d9 5c     : . \ 
    ld (hl),a           ;1619    77     w 
    ret                 ;161a    c9     . 
    call FLUSHCBUF      ;161b    cd 66 36     . f 6 
    call nz,SELWRTCBF   ;161e    c4 5f 36     . _ 6 
    ld a,(VAR_B_H)      ;1621    3a da 5c     : . \ 
    pop hl              ;1624    e1     . 
    push hl             ;1625    e5     . 
    ld bc,#19           ;1626    01 19 00     . . . 
    add hl,bc           ;1629    09     . 
    ld (hl),a           ;162a    77     w 
    pop hl              ;162b    e1     . 
    ld bc,16            ;162c    01 10 00     . . . 
    add hl,bc           ;162f    09     . 
    ld de,FILENAME      ;1630    11 dd 5c     . . \ 
    ld bc,16            ;1633    01 10 00     . . . 
    ldir                ;1636    ed b0     . . 
    call SEEKFILE01     ;1638    cd 4c 2d     . L - 
    jp nz,RNDRECORD05   ;163b    c2 6e 36     . n 6 
    call RD_STMFENT     ;163e    cd 72 34     . r 4 
    jr $+8              ;1641    18 06     . . 
    call FLUSHCBUF      ;1643    cd 66 36     . f 6 
    call nz,SELWRTCBF   ;1646    c4 5f 36     . _ 6 
    ld a,(VAR_C_L)      ;1649    3a db 5c     : . \ 
    ld c,14             ;164c    0e 0e     . . 
    rst 40              ;164e    ef     . 
    ld (hl),a           ;164f    77     w 
    push hl             ;1650    e5     . 
    call STREAMDRV      ;1651    cd d4 34     . . 4 
    call RD_CHBUFF      ;1654    cd a9 34     . . 4 
    pop hl              ;1657    e1     . 
    dec hl              ;1658    2b     + 
    ld a,(VAR_B_L)      ;1659    3a d9 5c     : . \ 
    ld (hl),a           ;165c    77     w 
    jr $-74             ;165d    18 b4     . . 
    call STREAMDRV      ;165f    cd d4 34     . . 4 
    call WR_CHBUFF      ;1662    cd 8d 34     . . 4 
    ret                 ;1665    c9     . 
    ld c,#23            ;1666    0e 23     . # 
    rst 40              ;1668    ef     . 
    ld a,(hl)           ;1669    7e     ~ 
    or a                ;166a    b7     . 
    ld (hl),0           ;166b    36 00     6 . 
    ret                 ;166d    c9     . 
    ld hl,(VAR_B_H)     ;166e    2a da 5c     * . \ 
    ld h,32             ;1671    26 20     &   
    ld (VAR_A_L),hl     ;1673    22 d7 5c     " . \ 
    ld hl,(VAR_B_L)     ;1676    2a d9 5c     * . \ 
    push hl             ;1679    e5     . 
    ld hl,(VAR_C_L)     ;167a    2a db 5c     * . \ 
    push hl             ;167d    e5     . 
    call NEWSEGMT02     ;167e    cd 15 34     . . 4 
    pop hl              ;1681    e1     . 
    ld (VAR_C_L),hl     ;1682    22 db 5c     " . \ 
    pop hl              ;1685    e1     . 
    ld (VAR_B_L),hl     ;1686    22 d9 5c     " . \ 
    jr $-64             ;1689    18 be     . . 
    push hl             ;168b    e5     . 
    ld hl,IF1VSWP       ;168c    21 8c 31     ! . 1 
    push hl             ;168f    e5     . 
    call IF1VSWP        ;1690    cd 8c 31     . . 1 
    ld hl,TVFLAG        ;1693    21 3c 5c     ! < \ 
    res 3,(hl)          ;1696    cb 9e     . . 
    xor a               ;1698    af     . 
    ld (PIP),a          ;1699    32 39 5c     2 9 \ 
    ld a,10             ;169c    3e 0a     > . 
    ld (CMP_SIZE),a     ;169e    32 06 5d     2 . ] 
    call READMODE       ;16a1    cd c1 36     . . 6 
    jr z,$+15           ;16a4    28 0d     ( . 
    cp 127              ;16a6    fe 7f     . © 
    jp nz,ER_INVSTM     ;16a8    c2 2e 35     . . 5 
    ld bc,19            ;16ab    01 13 00     . . . 
    add hl,bc           ;16ae    09     . 
    ld (hl),0           ;16af    36 00     6 . 
    jr $+5              ;16b1    18 03     . . 
    call ENDSTMFL       ;16b3    cd fc 34     . . 4 
    call CHBUFFADD      ;16b6    cd ab 33     . . 3 
    ld a,(hl)           ;16b9    7e     ~ 
    push af             ;16ba    f5     . 
    call INPNXTCHR      ;16bb    cd 2e 34     . . 4 
    pop af              ;16be    f1     . 
    scf                 ;16bf    37     7 
    ret                 ;16c0    c9     . 
    ld c,15             ;16c1    0e 0f     . . 
    rst 40              ;16c3    ef     . 
    ld a,(hl)           ;16c4    7e     ~ 
    or a                ;16c5    b7     . 
    ret                 ;16c6    c9     . 
    ld hl,(DSTMADDR)    ;16c7    2a 11 5d     * . ] 
    ld (CH_ADD),hl      ;16ca    22 5d 5c     " ] \ 
    call GETARG_I       ;16cd    cd a8 2e     . . . 
    call SYN_CHCK       ;16d0    cd 0e 2e     . . . 
    ld a,(VAR_C_L)      ;16d3    3a db 5c     : . \ 
    ld hl,#1727         ;16d6    21 27 17     ! ' . 
    call CALLBAS        ;16d9    cd 36 2e     . 6 . 
    ld a,b              ;16dc    78     x 
    or c                ;16dd    b1     . 
    jp z,DSTM_RET       ;16de    ca 70 21     . p ! 
    push hl             ;16e1    e5     . 
    ld hl,(CHANS)       ;16e2    2a 4f 5c     * O \ 
    add hl,bc           ;16e5    09     . 
    ld a,(hl)           ;16e6    7e     ~ 
    ld hl,CH_OUTPUT     ;16e7    21 0f 3c     ! . < 
    cp h                ;16ea    bc     . 
    pop hl              ;16eb    e1     . 
    jp nz,ER_NDFILE     ;16ec    c2 bc 32     . . 2 
    ld (hl),0           ;16ef    36 00     6 . 
    inc hl              ;16f1    23     # 
    ld (hl),0           ;16f2    36 00     6 . 
    ld (VAR_B_L),bc     ;16f4    ed 43 d9 5c     . C . \ 
    ld hl,(CHANS)       ;16f8    2a 4f 5c     * O \ 
    add hl,bc           ;16fb    09     . 
    dec hl              ;16fc    2b     + 
    ld (VAR_A_L),hl     ;16fd    22 d7 5c     " . \ 
    call FLUCHBUFF      ;1700    cd 42 37     . B 7 
    ld hl,(VAR_A_L)     ;1703    2a d7 5c     * . \ 
    ld bc,#0124         ;1706    01 24 01     . $ . 
    call BAS_RECLM      ;1709    cd d7 2e     . . . 
    ld hl,STRMS         ;170c    21 10 5c     ! . \ 
    ld b,16             ;170f    06 10     . . 
    push bc             ;1711    c5     . 
    ld bc,(VAR_B_L)     ;1712    ed 4b d9 5c     . K . \ 
    ld e,(hl)           ;1716    5e     ^ 
    inc hl              ;1717    23     # 
    ld d,(hl)           ;1718    56     V 
    ex de,hl            ;1719    eb     . 
    sbc hl,bc           ;171a    ed 42     . B 
    ex de,hl            ;171c    eb     . 
    jr c,$+19           ;171d    38 11     8 . 
    ld d,(hl)           ;171f    56     V 
    dec hl              ;1720    2b     + 
    ld e,(hl)           ;1721    5e     ^ 
    inc hl              ;1722    23     # 
    push hl             ;1723    e5     . 
    ex de,hl            ;1724    eb     . 
    ld bc,#0124         ;1725    01 24 01     . $ . 
    sbc hl,bc           ;1728    ed 42     . B 
    ex de,hl            ;172a    eb     . 
    pop hl              ;172b    e1     . 
    ld (hl),d           ;172c    72     r 
    dec hl              ;172d    2b     + 
    ld (hl),e           ;172e    73     s 
    inc hl              ;172f    23     # 
    inc hl              ;1730    23     # 
    pop bc              ;1731    c1     . 
    djnz $-33           ;1732    10 dd     . . 
    ld hl,(DSTMADDR)    ;1734    2a 11 5d     * . ] 
    ld bc,#0124         ;1737    01 24 01     . $ . 
    sbc hl,bc           ;173a    ed 42     . B 
    ld (DSTMADDR),hl    ;173c    22 11 5d     " . ] 
    jp DSTM_RET         ;173f    c3 70 21     . p ! 
    ld bc,15            ;1742    01 0f 00     . . . 
    add hl,bc           ;1745    09     . 
    ld a,(hl)           ;1746    7e     ~ 
    or a                ;1747    b7     . 
    ret z               ;1748    c8     . 
    ld hl,(VAR_A_L)     ;1749    2a d7 5c     * . \ 
    ld (CURCHL),hl      ;174c    22 51 5c     " Q \ 
    call WR_STMFENT     ;174f    cd 55 37     . U 7 
    jp WR_CHBUFF        ;1752    c3 8d 34     . . 4 
    ld bc,13            ;1755    01 0d 00     . . . 
    add hl,bc           ;1758    09     . 
    ld e,(hl)           ;1759    5e     ^ 
    inc hl              ;175a    23     # 
    ld d,(hl)           ;175b    56     V 
    ld bc,13            ;175c    01 0d 00     . . . 
    add hl,bc           ;175f    09     . 
    ld (hl),e           ;1760    73     s 
    inc hl              ;1761    23     # 
    ld (hl),d           ;1762    72     r 
    ld c,16             ;1763    0e 10     . . 
    rst 40              ;1765    ef     . 
    ld de,FILENAME      ;1766    11 dd 5c     . . \ 
    ld bc,16            ;1769    01 10 00     . . . 
    ldir                ;176c    ed b0     . . 
    call STREAMDRV      ;176e    cd d4 34     . . 4 
    ld c,12             ;1771    0e 0c     . . 
    rst 40              ;1773    ef     . 
    ld c,(hl)           ;1774    4e     N 
    call PUTENTRY       ;1775    cd bc 27     . . ' 
    jp WRT_BUFFER       ;1778    c3 f0 2e     . . . 
    ld a,(hl)           ;177b    7e     ~ 
    or a                ;177c    b7     . 
    ret z               ;177d    c8     . 
    and 127             ;177e    e6 7f     . © 
    rst 16              ;1780    d7     . 
    bit 7,(hl)          ;1781    cb 7e     . ~ 
    ret nz              ;1783    c0     . 
    inc hl              ;1784    23     # 
    jr $-10             ;1785    18 f4     . . 
    ld a,(de)           ;1787    1a     . 
    cp (hl)             ;1788    be     . 
    ret nz              ;1789    c0     . 
    inc de              ;178a    13     . 
    inc hl              ;178b    23     # 
    djnz $-5            ;178c    10 f9     . . 
    ret                 ;178e    c9     . 
    ld hl,M_NODISK      ;178f    21 cf 37     ! . 7 
    ld a,6              ;1792    3e 06     > . 
    jp DSTM_ERRET       ;1794    c3 e5 2c     . . , 
    ld hl,M_DIRFULL     ;1797    21 c0 37     ! . 7 
    ld a,4              ;179a    3e 04     > . 
    jp DSTM_ERRET       ;179c    c3 e5 2c     . . , 
    ld a,#1A            ;179f    3e 1a     > . 
    jr $+4              ;17a1    18 02     . . 
    ld a,18             ;17a3    3e 12     > . 
    ld (ERR_NR),a       ;17a5    32 3a 5c     2 : \ 
    ret                 ;17a8    c9     . 
    ld a,3              ;17a9    3e 03     > . 
    jr $-6              ;17ab    18 f8     . . 

;------------------------------------------------------------------------------
; Mirror #17AD/6061 of messages (#37AD/14253-#380E/14350)
;------------------------------------------------------------------------------
    defm "*BREAK*"
    defb #8D            ; #80+'Enter' (end of string marker).

    defm "Out of RAM"
    defb #8D            ; #80+'Enter' (end of string marker).

    defm "Directory full"
    defb #8D            ; #80+'Enter' (end of string marker).

    defm "No disk"
    defb #8D            ; #80+'Enter' (end of string marker).

    defm "Stream opened"
    defb #8D            ; #80+'Enter' (end of string marker).

    defm "Not disk file"
    defb #8D            ; #80+'Enter' (end of string marker).

    defm "File exists"
    defb #0D            ; 'Enter'
    defm "Over write?"
    defm "(Y/N"
    defb #A9            ; ")"+#80 (end of string marker).
;------------------------------------------------------------------------------

;------------------------------------------------------------------------------
; Unused bytes and codes (#180F/6159-#18F0/6384)
;------------------------------------------------------------------------------
    push af             ;180f    f5     . 
    push bc             ;1810    c5     . 
    ld (DETEMP),de      ;1811    ed 53 04 5d     . S . ] 
    ld (HLTEMP),hl      ;1815    22 02 5d     " . ] 
    call IF1VSWP        ;1818    cd 8c 31     . . 1 
    ld a,#FF            ;181b    3e ff     > . 
    ld (RM_FPC),a       ;181d    32 1f 5d     2 . ] 
    pop bc              ;1820    c1     . 
    pop af              ;1821    f1     . 
    ld hl,BASDOSRET     ;1822    21 a4 21     ! . ! 
    ld (DOS_RET),hl     ;1825    22 1a 5d     " . ] 
    ld hl,0             ;1828    21 00 00     ! . . 
    add hl,sp           ;182b    39     9 
    ld (OLDSP),hl       ;182c    22 1c 5d     " . ] 
    dec hl              ;182f    2b     + 
    dec hl              ;1830    2b     + 
    ld sp,hl            ;1831    f9     . 
    push af             ;1832    f5     . 
    call DEF_ERRSP      ;1833    cd c0 21     . . ! 
    ld hl,0385ah        ;1836    21 5a 38     ! Z 8 
    ld a,(hl)           ;1839    7e     ~ 
    cp c                ;183a    b9     . 
    jr nz,$+20          ;183b    20 12       . 
    pop af              ;183d    f1     . 
    inc hl              ;183e    23     # 
    ld e,(hl)           ;183f    5e     ^ 
    inc hl              ;1840    23     # 
    ld d,(hl)           ;1841    56     V 
    ld hl,DSTM_RET      ;1842    21 70 21     ! p ! 
    push hl             ;1845    e5     . 
    push de             ;1846    d5     . 
    ld hl,(HLTEMP)      ;1847    2a 02 5d     * . ] 
    ld de,(DETEMP)      ;184a    ed 5b 04 5d     . [ . ] 
    ret                 ;184e    c9     . 
    cp #FF              ;184f    fe ff     . . 
    jr nz,$+4           ;1851    20 02       . 
    pop af              ;1853    f1     . 
    ret                 ;1854    c9     . 
    inc hl              ;1855    23     # 
    inc hl              ;1856    23     # 
    inc hl              ;1857    23     # 
    jr $-31             ;1858    18 df     . . 
    nop                 ;185a    00     . 
    dec a               ;185b    3d     = 
    dec a               ;185c    3d     = 
    ld bc,SEL_DRIVE01   ;185d    01 74 3d     . t = 
    ld (bc),a           ;1860    02     . 
    inc c               ;1861    0c     . 
    ld a,3              ;1862    3e 03     > . 
    sbc a,e             ;1864    9b     . 
    ld a,4              ;1865    3e 04     > . 
    sbc a,a             ;1867    9f     . 
    ld a,5              ;1868    3e 05     > . 
    jp pe,#062E         ;186a    ea 2e 06     . . . 
    jp m,#072E          ;186d    fa 2e 07     . . . 
    sbc a,d             ;1870    9a     . 
    jr c,$+10           ;1871    38 08     8 . 
    xor l               ;1873    ad     . 
    daa                 ;1874    27     ' 
    add hl,bc           ;1875    09     . 
    or l                ;1876    b5     . 
    daa                 ;1877    27     ' 
    ld a,(bc)           ;1878    0a     . 
    adc a,c             ;1879    89     . 
    dec l               ;187a    2d     - 
    dec bc              ;187b    0b     . 
    cp l                ;187c    bd     . 
    jr c,$+14           ;187d    38 0c     8 . 
    or h                ;187f    b4     . 
    jr c,$+15           ;1880    38 0d     8 . 
    ld (hl),b           ;1882    70     p 
    ld hl,#D10E         ;1883    21 0e d1     ! . . 
    jr c,$+17           ;1886    38 0f     8 . 
    ld (hl),b           ;1888    70     p 
    ld hl,#7010         ;1889    21 10 70     ! . p 
    ld hl,#7011         ;188c    21 11 70     ! . p 
    ld hl,#E812         ;188f    21 12 e8     ! . . 
    jr c,$+21           ;1892    38 13     8 . 
    and d               ;1894    a2     . 
    jr c,$+22           ;1895    38 14     8 . 
    and l               ;1897    a5     . 
    jr c,$+1            ;1898    38 ff     8 . 
    push af             ;189a    f5     . 
    call ID_TYPE        ;189b    cd 84 23     . . # 
    pop af              ;189e    f1     . 
    jp #23f6            ;189f    c3 f6 23     . . # 
    xor a               ;18a2    af     . 
    jr $+4              ;18a3    18 02     . . 
    ld a,#FF            ;18a5    3e ff     > . 
    ld de,FILENAME      ;18a7    11 dd 5c     . . \ 
    ld bc,16            ;18aa    01 10 00     . . . 
    or a                ;18ad    b7     . 
    jr z,$+3            ;18ae    28 01     ( . 
    ex de,hl            ;18b0    eb     . 
    ldir                ;18b1    ed b0     . . 
    ret                 ;18b3    c9     . 
    call ID_TYPE        ;18b4    cd 84 23     . . # 
    call DIRFULL        ;18b7    cd 6e 2b     . n + 
    jp #2BD1            ;18ba    c3 d1 2b     . . + 
    ld (VAR_A_L),hl     ;18bd    22 d7 5c     " . \ 
    ld (VAR_B_L),de     ;18c0    ed 53 d9 5c     . S . \ 
    ld (VAR_C_L),de     ;18c4    ed 53 db 5c     . S . \ 
    call ID_TYPE        ;18c8    cd 84 23     . . # 
    call DIRFULL        ;18cb    cd 6e 2b     . n + 
    jp DS_SAVE07        ;18ce    c3 fd 2b     . . + 
    or a                ;18d1    b7     . 
    ld (CODEARG),a      ;18d2    32 d6 5c     2 . \ 
    ld (VAR_B_L),hl     ;18d5    22 d9 5c     " . \ 
    ld (VAR_C_L),de     ;18d8    ed 53 db 5c     . S . \ 
    call SEEKFILE01     ;18dc    cd 4c 2d     . L - 
    call #29D3          ;18df    cd d3 29     . . ) 
    call LOADPARM       ;18e2    cd dd 29     . . ) 
    jp FILELOAD01       ;18e5    c3 4d 2a     . M * 
    call ID_TYPE        ;18e8    cd 84 23     . . # 
    call SEEKFILE01     ;18eb    cd 4c 2d     . L - 
    jp ERASEFILE        ;18ee    c3 44 27     . D ' 
;------------------------------------------------------------------------------

    call GET_FNAME      ;18f1    cd f2 2c     . . , 
    call ID_TYPE        ;18f4    cd 84 23     . . # 
    jp SEEKFILE01       ;18f7    c3 4c 2d     . L - 
    push bc             ;18fa    c5     . 
    ld b,%00001000      ;18fb    06 08     . . 
    ld a,(hl)           ;18fd    7e     ~ 
    rst 16              ;18fe    d7     . 
    inc hl              ;18ff    23     # 
    djnz $-3            ;1900    10 fb     . . 
    ld a,#3C            ;1902    3e 3c     > < 
    rst 16              ;1904    d7     . 
    ld a,(hl)           ;1905    7e     ~ 
    rst 16              ;1906    d7     . 
    ld a,#3E            ;1907    3e 3e     > > 
    rst 16              ;1909    d7     . 
    pop bc              ;190a    c1     . 
    ret                 ;190b    c9     . 
    ld c,a              ;190c    4f     O 
    ld b,0              ;190d    06 00     . . 
    jp BAS_PRNTBC       ;190f    c3 45 2e     . E . 
    call CALLBAS        ;1912    cd 36 2e     . 6 . 
    jp LOADCFGS         ;1915    c3 2b 39     . + 9 
    push bc             ;1918    c5     . 
    push af             ;1919    f5     . 
    ld hl,#5BE0         ;191a    21 e0 5b     ! . [ 
    ld bc,32            ;191d    01 20 00     .   . 
    ld de,NODISK        ;1920    11 d1 5c     . . \ 
    ldir                ;1923    ed b0     . . 
    call IF1VSWP        ;1925    cd 8c 31     . . 1 
    pop af              ;1928    f1     . 
    pop bc              ;1929    c1     . 
    ret                 ;192a    c9     . 
    push af             ;192b    f5     . 
    call IF1VSWP        ;192c    cd 8c 31     . . 1 
    ld hl,NODISK        ;192f    21 d1 5c     ! . \ 
    ld de,#5BE0         ;1932    11 e0 5b     . . [ 
    ld bc,32            ;1935    01 20 00     .   . 
    pop af              ;1938    f1     . 
    ldir                ;1939    ed b0     . . 
    ret                 ;193b    c9     . 
    xor a               ;193c    af     . 
    ld (VAR_A_L),a      ;193d    32 d7 5c     2 . \ 
    call SYN_CHCK       ;1940    cd 0e 2e     . . . 
    call NOARG          ;1943    cd aa 23     . . # 
    jp z,ER_SYNTX       ;1946    ca b3 2d     . . - 
    call FT_DSKTYPE     ;1949    cd ba 3d     . . = 
    ld a,(VAR_A_L)      ;194c    3a d7 5c     : . \ 
    ld (hl),a           ;194f    77     w 
    jp DSTM_RET         ;1950    c3 70 21     . p ! 
    ld a,#80            ;1953    3e 80     > . 
    jr $-24             ;1955    18 e6     . . 

;------------------------------------------------------------------------------
; Mirror (#1957/6487) of messages (#3957/14679)
;------------------------------------------------------------------------------
    defb #0D            ;       'Enter'
    defm "*ERROR*"
    defb #8D            ;       'Enter'+#80 (end of string marker)

    defb #0D            ;       'Enter'
    defm "No space"
    defb #8D            ;       'Enter'+#80 (end of string marker)

    defb #0D            ;       'Enter'
    defm "File exists"
    defb #8D            ;       'Enter'+#80 (end of string marker).

    defm " Free"
    defb #8D            ;       'Enter'+#80 (end of string marker).

    defb #0D            ;       'Enter'
    defm "Read Onl"
    defb #F9            ;       "y"+#80, (end of string marker).

    defb #0D            ;       'Enter'.
    defm "Disc Erro"
    defb #F2            ;       "r"+#80 (end of string marker).

    defb #0D            ;       'Enter'
    defm "Rec.  O/"
    defb #C6            ;       "F"+#80 (end of string marker).

    defm "Title:"
    defb #A0            ;       End of string marker, 'Space'+#80

    defb #0D            ;       'Enter'.
    defm "Retry,"
    defm "Abort,"
    defm "Ignore?"
    defb #00            ;       End of string marker.

    defb #0D            ;       'Enter'
    defb "Trk"
    defb #A0            ;       End of string marker, 'Space'+#80

    defm " sec"
    defb #A0            ;       End of string marker, 'Space'+#80

    defm " Del. File"
    defb #8D            ;       'Enter'+#80 (end of string marker)

    defb #0D            ;       'Enter'
    defm "No"

    defm " File(s)"
    defb #8D            ;       'Enter'+#80 (end of string marker)
    defb #00            ;       Final end marker.
;------------------------------------------------------------------------------

    push af             ;19da    f5     . 
    push bc             ;19db    c5     . 
    push de             ;19dc    d5     . 
    push hl             ;19dd    e5     . 
    push ix             ;19de    dd e5     . . 
    push iy             ;19e0    fd e5     . . 
    exx                 ;19e2    d9     . 
    push bc             ;19e3    c5     . 
    push de             ;19e4    d5     . 
    push hl             ;19e5    e5     . 
    ex af,af'           ;19e6    08     . 
    push af             ;19e7    f5     . 
    ld a,i              ;19e8    ed 57     . W 
    push af             ;19ea    f5     . 
    ld a,r              ;19eb    ed 5f     . _ 
    push af             ;19ed    f5     . 
    ld hl,0             ;19ee    21 00 00     ! . . 
    add hl,sp           ;19f1    39     9 
    push hl             ;19f2    e5     . 
    ld a,#3C            ;19f3    3e 3c     > < 
    out (255),a         ;19f5    d3 ff     . . 
    call NMI_RESTORE    ;19f7    cd ed 3b     . . ; 
    call LONGDELAY      ;19fa    cd 3d 3e     . = > 
    ld de,#000A         ;19fd    11 0a 00     . . . 
    ld hl,VID_RAM       ;1a00    21 00 40     ! . @ 
    push hl             ;1a03    e5     . 
    call NMI_WRSEC      ;1a04    cd b2 3a     . . : 
    pop hl              ;1a07    e1     . 
    push hl             ;1a08    e5     . 
    ld de,8             ;1a09    11 08 00     . . . 
    call NMI_RDSEC      ;1a0c    cd a7 3b     . . ; 
    ld hl,VID_RAM+226   ;1a0f    21 e2 40     ! . @ 
    ld a,(hl)           ;1a12    7e     ~ 
    add a,12            ;1a13    c6 0c     . . 
    ld (hl),a           ;1a15    77     w 
    inc hl              ;1a16    23     # 
    ld a,(hl)           ;1a17    7e     ~ 
    ld (KSTATE),a       ;1a18    32 00 5c     2 . \ 
    inc hl              ;1a1b    23     # 
    ld a,(hl)           ;1a1c    7e     ~ 
    or a                ;1a1d    b7     . 
    jr nz,$+23          ;1a1e    20 15       . 
    inc (hl)            ;1a20    34     4 
    inc hl              ;1a21    23     # 
    ld e,(hl)           ;1a22    5e     ^ 
    inc hl              ;1a23    23     # 
    ld d,(hl)           ;1a24    56     V 
    ld hl,#FF40         ;1a25    21 40 ff     ! @ . 
    add hl,de           ;1a28    19     . 
    ld (VID_RAM+229),hl ;1a29    22 e5 40     " . @ 
    ld hl,VID_RAM       ;1a2c    21 00 40     ! . @ 
    ld de,8             ;1a2f    11 08 00     . . . 
    call NMI_WRSEC      ;1a32    cd b2 3a     . . : 
    pop hl              ;1a35    e1     . 
    ld de,#000A         ;1a36    11 0a 00     . . . 
    call NMI_RDSEC      ;1a39    cd a7 3b     . . ; 
    call RAMDUMP        ;1a3c    cd 87 3a     . . : 
    ld a,#3C            ;1a3f    3e 3c     > < 
    out (255),a         ;1a41    d3 ff     . . 
    call NMI_RESTORE    ;1a43    cd ed 3b     . . ; 
    ld hl,VID_RAM       ;1a46    21 00 40     ! . @ 
    ld de,0             ;1a49    11 00 00     . . . 
    call NMI_RDSEC      ;1a4c    cd a7 3b     . . ; 
    ld (hl),#40         ;1a4f    36 40     6 @ 
    inc hl              ;1a51    23     # 
    ld b,7              ;1a52    06 07     . . 
    ld (hl),32          ;1a54    36 20     6   
    inc hl              ;1a56    23     # 
    djnz $-3            ;1a57    10 fb     . . 
    ld (hl),#43         ;1a59    36 43     6 C 
    pop hl              ;1a5b    e1     . 
    ld (VID_RAM+9),hl   ;1a5c    22 09 40     " . @ 
    ld hl,256           ;1a5f    21 00 01     ! . . 
    ld (VID_RAM+14),hl  ;1a62    22 0e 40     " . @ 
    ld a,#C0            ;1a65    3e c0     > . 
    ld (VID_RAM+13),a   ;1a67    32 0d 40     2 . @ 
    ld hl,VID_RAM       ;1a6a    21 00 40     ! . @ 
    ld de,0             ;1a6d    11 00 00     . . . 
    call NMI_WRSEC      ;1a70    cd b2 3a     . . : 
    ld hl,VID_RAM       ;1a73    21 00 40     ! . @ 
    ld de,256           ;1a76    11 00 01     . . . 
    ld c,1              ;1a79    0e 01     . . 
    call NMI_SEEKL      ;1a7b    cd c5 3b     . . ; 
    call NMI_RDSEC      ;1a7e    cd a7 3b     . . ; 
    ld a,#3C            ;1a81    3e 3c     > < 
    push af             ;1a83    f5     . 
    jp REG_REC          ;1a84    c3 64 3b     . d ; 
    call NMI_RESTORE    ;1a87    cd ed 3b     . . ; 
    ld c,1              ;1a8a    0e 01     . . 
    call NMI_SEEKL      ;1a8c    cd c5 3b     . . ; 
    ld hl,VID_RAM       ;1a8f    21 00 40     ! . @ 
    ld de,256           ;1a92    11 00 01     . . . 
    ld b,#C0            ;1a95    06 c0     . . 
    push bc             ;1a97    c5     . 
    push de             ;1a98    d5     . 
    call NMI_WRSEC      ;1a99    cd b2 3a     . . : 
    ld de,256           ;1a9c    11 00 01     . . . 
    add hl,de           ;1a9f    19     . 
    pop de              ;1aa0    d1     . 
    inc e               ;1aa1    1c     . 
    ld a,e              ;1aa2    7b     { 
    cp 16               ;1aa3    fe 10     . . 
    jr nz,$+9           ;1aa5    20 07       . 
    ld e,0              ;1aa7    1e 00     . . 
    inc d               ;1aa9    14     . 
    ld c,d              ;1aaa    4a     J 
    call NMI_SEEKL      ;1aab    cd c5 3b     . . ; 
    pop bc              ;1aae    c1     . 
    djnz $-24           ;1aaf    10 e6     . . 
    ret                 ;1ab1    c9     . 
    ld a,e              ;1ab2    7b     { 
    inc a               ;1ab3    3c     < 
    out (95),a          ;1ab4    d3 5f     . _ 
    push hl             ;1ab6    e5     . 
    ld d,10             ;1ab7    16 0a     . . 
    push de             ;1ab9    d5     . 
    ld c,127            ;1aba    0e 7f     . © 
    ld a,#A0            ;1abc    3e a0     > . 
    out (31),a          ;1abe    d3 1f     . . 
    call FDC_WDATA02    ;1ac0    cd 60 3f     . ` ? 
    pop de              ;1ac3    d1     . 
    pop hl              ;1ac4    e1     . 
    in a,(31)           ;1ac5    db 1f     . . 
    and 127             ;1ac7    e6 7f     . © 
    ret z               ;1ac9    c8     . 
    dec d               ;1aca    15     . 
    push hl             ;1acb    e5     . 
    push de             ;1acc    d5     . 
    jr nz,$-19          ;1acd    20 eb       . 
    halt                ;1acf    76     v 
    call GET1ARG_S      ;1ad0    cd 7c 2e     . | . 
    call SYN_CHCK       ;1ad3    cd 0e 2e     . . . 
    call FIND_FTYPE     ;1ad6    cd f1 24     . . $ 
    call USTK_FILE      ;1ad9    cd f1 38     . . 8 
    jp nz,ER_NOFILE     ;1adc    c2 58 23     . X # 
    call GETENTRY       ;1adf    cd ae 27     . . ' 
    ld a,(FILENAME)     ;1ae2    3a dd 5c     : . \ 
    cp #24              ;1ae5    fe 24     . $ 
    jr nz,$+4           ;1ae7    20 02       . 
    im 2                ;1ae9    ed 5e     . ^ 
    ld sp,VID_RAM+240   ;1aeb    31 f0 40     1 . @ 
    call FT_DSKTYPE     ;1aee    cd ba 3d     . . = 
    ld (VID_RAM+16),a   ;1af1    32 10 40     2 . @ 
    ld a,(PORT255)      ;1af4    3a 16 5d     : . ] 
    ld (VID_RAM+17),a   ;1af7    32 11 40     2 . @ 
    ld hl,(FILEPARM1)   ;1afa    2a e6 5c     * . \ 
    push hl             ;1afd    e5     . 
    ld de,(FILESECT)    ;1afe    ed 5b eb 5c     . [ . \ 
    push de             ;1b02    d5     . 
    inc e               ;1b03    1c     . 
    ld a,e              ;1b04    7b     { 
    cp 16               ;1b05    fe 10     . . 
    jr nz,$+5           ;1b07    20 03       . 
    ld e,0              ;1b09    1e 00     . . 
    inc d               ;1b0b    14     . 
    ld c,d              ;1b0c    4a     J 
    call GOTO_SIDE0     ;1b0d    cd 93 3b     . . ; 
    ld a,(VID_RAM+16)   ;1b10    3a 10 40     : . @ 
    and 2               ;1b13    e6 02     . . 
    call nz,GOTO_SIDE1  ;1b15    c4 9b 3b     . . ; 
    ld a,c              ;1b18    79     y 
    call NMI_SEEKA      ;1b19    cd db 3b     . . ; 
    ld hl,VID_RAM+256   ;1b1c    21 00 41     ! . A 
    ld b,#BF            ;1b1f    06 bf     . . 
    push bc             ;1b21    c5     . 
    push de             ;1b22    d5     . 
    call NMI_RDSEC      ;1b23    cd a7 3b     . . ; 
    ld de,256           ;1b26    11 00 01     . . . 
    add hl,de           ;1b29    19     . 
    pop de              ;1b2a    d1     . 
    inc e               ;1b2b    1c     . 
    ld a,e              ;1b2c    7b     { 
    cp 16               ;1b2d    fe 10     . . 
    jr nz,$+21          ;1b2f    20 13       . 
    ld e,0              ;1b31    1e 00     . . 
    inc d               ;1b33    14     . 
    ld c,d              ;1b34    4a     J 
    call GOTO_SIDE0     ;1b35    cd 93 3b     . . ; 
    ld a,(VID_RAM+16)   ;1b38    3a 10 40     : . @ 
    and 2               ;1b3b    e6 02     . . 
    call nz,GOTO_SIDE1  ;1b3d    c4 9b 3b     . . ; 
    ld a,c              ;1b40    79     y 
    call NMI_SEEKA      ;1b41    cd db 3b     . . ; 
    pop bc              ;1b44    c1     . 
    djnz $-36           ;1b45    10 da     . . 
    pop de              ;1b47    d1     . 
    pop hl              ;1b48    e1     . 
    ld sp,hl            ;1b49    f9     . 
    ld a,(VID_RAM+17)   ;1b4a    3a 11 40     : . @ 
    push af             ;1b4d    f5     . 
    ld c,d              ;1b4e    4a     J 
    call GOTO_SIDE0     ;1b4f    cd 93 3b     . . ; 
    ld a,(VID_RAM+16)   ;1b52    3a 10 40     : . @ 
    and 2               ;1b55    e6 02     . . 
    call nz,GOTO_SIDE1  ;1b57    c4 9b 3b     . . ; 
    ld a,c              ;1b5a    79     y 
    call NMI_SEEKA      ;1b5b    cd db 3b     . . ; 
    ld hl,VID_RAM       ;1b5e    21 00 40     ! . @ 
    call NMI_RDSEC      ;1b61    cd a7 3b     . . ; 
    pop af              ;1b64    f1     . 
    ex af,af'           ;1b65    08     . 
    pop af              ;1b66    f1     . 
    ld r,a              ;1b67    ed 4f     . O 
    pop af              ;1b69    f1     . 
    ld i,a              ;1b6a    ed 47     . G 
    jp po,REG_REC01     ;1b6c    e2 81 3b     . . ; 
    pop af              ;1b6f    f1     . 
    pop hl              ;1b70    e1     . 
    pop de              ;1b71    d1     . 
    pop bc              ;1b72    c1     . 
    exx                 ;1b73    d9     . 
    ex af,af'           ;1b74    08     . 
    pop iy              ;1b75    fd e1     . . 
    pop ix              ;1b77    dd e1     . . 
    pop hl              ;1b79    e1     . 
    pop de              ;1b7a    d1     . 
    pop bc              ;1b7b    c1     . 
    or #80              ;1b7c    f6 80     . . 
    jp REGREC_EI        ;1b7e    c3 88 3c     . . < 
    pop af              ;1b81    f1     . 
    pop hl              ;1b82    e1     . 
    pop de              ;1b83    d1     . 
    pop bc              ;1b84    c1     . 
    exx                 ;1b85    d9     . 
    ex af,af'           ;1b86    08     . 
    pop iy              ;1b87    fd e1     . . 
    pop ix              ;1b89    dd e1     . . 
    pop hl              ;1b8b    e1     . 
    pop de              ;1b8c    d1     . 
    pop bc              ;1b8d    c1     . 
    or #80              ;1b8e    f6 80     . . 
    jp REGREC_DI        ;1b90    c3 90 3c     . . < 
    ld a,(VID_RAM+17)   ;1b93    3a 11 40     : . @ 
    or #3C              ;1b96    f6 3c     . < 
    out (255),a         ;1b98    d3 ff     . . 
    ret                 ;1b9a    c9     . 
    ld a,c              ;1b9b    79     y 
    or a                ;1b9c    b7     . 
    rra                 ;1b9d    1f     . 
    ld c,a              ;1b9e    4f     O 
    ret nc              ;1b9f    d0     . 
    ld a,(VID_RAM+17)   ;1ba0    3a 11 40     : . @ 
    and #6F             ;1ba3    e6 6f     . o 
    jr $-13             ;1ba5    18 f1     . . 
    ld a,e              ;1ba7    7b     { 
    inc a               ;1ba8    3c     < 
    out (95),a          ;1ba9    d3 5f     . _ 
    push hl             ;1bab    e5     . 
    ld d,10             ;1bac    16 0a     . . 
    push de             ;1bae    d5     . 
    ld c,127            ;1baf    0e 7f     . © 
    ld a,#80            ;1bb1    3e 80     > . 
    out (31),a          ;1bb3    d3 1f     . . 
    call FDC_RDATA02    ;1bb5    cd 7b 3f     . { ? 
    pop de              ;1bb8    d1     . 
    pop hl              ;1bb9    e1     . 
    in a,(31)           ;1bba    db 1f     . . 
    and 127             ;1bbc    e6 7f     . © 
    ret z               ;1bbe    c8     . 
    dec d               ;1bbf    15     . 
    push hl             ;1bc0    e5     . 
    push de             ;1bc1    d5     . 
    jr nz,$-19          ;1bc2    20 eb       . 
    halt                ;1bc4    76     v 
    ld a,#3C            ;1bc5    3e 3c     > < 
    out (255),a         ;1bc7    d3 ff     . . 
    ld a,(KSTATE)       ;1bc9    3a 00 5c     : . \ 
    and %00001000       ;1bcc    e6 08     . . 
    jr nz,$+12          ;1bce    20 0a       . 
    ld a,c              ;1bd0    79     y 
    or a                ;1bd1    b7     . 
    rra                 ;1bd2    1f     . 
    ld c,a              ;1bd3    4f     O 
    jr nc,$+6           ;1bd4    30 04     0 . 
    ld a,#2C            ;1bd6    3e 2c     > , 
    out (255),a         ;1bd8    d3 ff     . . 
    ld a,c              ;1bda    79     y 
    out (127),a         ;1bdb    d3 7f     . © 
    ld a,#1B            ;1bdd    3e 1b     > . 
    out (31),a          ;1bdf    d3 1f     . . 
    in a,(255)          ;1be1    db ff     . . 
    and #80             ;1be3    e6 80     . . 
    jr z,$-4            ;1be5    28 fa     ( . 
    push bc             ;1be7    c5     . 
    call DELAY          ;1be8    cd a6 3d     . . = 
    pop bc              ;1beb    c1     . 
    ret                 ;1bec    c9     . 
    ld a,11             ;1bed    3e 0b     > . 
    jr $-16             ;1bef    18 ee     . . 

;------------------------------------------------------------------------------
; Unused bytes and codes (#1BF1/7153-#1BFF/7167)
;------------------------------------------------------------------------------
    defb #FF,#FF,#FF,#FF
    defb #FF,#FF,#FF,#FF
    defb #FF
    jp IF1VSWP          ;#318C
    jp #380F
;------------------------------------------------------------------------------

    jp DOS_CLI01        ;1c00    c3 49 3c     . I < 
    jp DOS_BASIC01      ;1c03    c3 30 3c     . 0 < 
    jp ROMBETA_R        ;1c06    c3 68 3c     . h < 
    call ROMBETA_R      ;1c09    cd 68 3c     . h < 
    jp CH_INP01         ;1c0c    c3 8b 36     . . 6 
    call ROMBETA_R      ;1c0f    cd 68 3c     . h < 
    jp CH_OUT01         ;1c12    c3 db 34     . . 4 
    ld hl,(OLDSP)       ;1c15    2a 1c 5d     * . ] 
    dec hl              ;1c18    2b     + 
    dec hl              ;1c19    2b     + 
    ld sp,hl            ;1c1a    f9     . 
    call ROMBETA_R      ;1c1b    cd 68 3c     . h < 
    jp DOSERROR01       ;1c1e    c3 c8 2d     . . - 
    ld sp,(ERR_SP)      ;1c21    ed 7b 3d 5c     . { = \ 
    ld a,(LDPKEXEC)     ;1c25    3a 10 5d     : . ] 
    or a                ;1c28    b7     . 
    jp z,#1B76          ;1c29    ca 76 1b     . v . 
    pop hl              ;1c2c    e1     . 
    jp #12CF            ;1c2d    c3 cf 12     . . . 
    call INITDOS        ;1c30    cd 37 3c     . 7 < 
    push hl             ;1c33    e5     . 
    jp DOS_BASIC02      ;1c34    c3 24 21     . $ ! 
    ld a,(FLAGBUFF)     ;1c37    3a 17 5d     : . ] 
    cp #AA              ;1c3a    fe aa     . . 
    call nz,INITVARS    ;1c3c    c4 d6 3c     . . < 
    jr $+41             ;1c3f    18 27     . ' 
    ld a,#FF            ;1c41    3e ff     > . 
    ld (PORT255),a      ;1c43    32 16 5d     2 . ] 
    call ROM_BASIC      ;1c46    cd 7c 3c     . | < 
    call INITDOS        ;1c49    cd 37 3c     . 7 < 
    push hl             ;1c4c    e5     . 
    jp DOS_CLI02        ;1c4d    c3 dc 21     . . ! 
    rst 32              ;1c50    e7     . 
    ld (DETEMP),de      ;1c51    ed 53 04 5d     . S . ] 
    pop de              ;1c55    d1     . 
    pop hl              ;1c56    e1     . 
    push de             ;1c57    d5     . 
    call ROM_BASIC      ;1c58    cd 7c 3c     . | < 
    ld de,ROM_BETA      ;1c5b    11 6b 3c     . k < 
    push de             ;1c5e    d5     . 
    push hl             ;1c5f    e5     . 
    ld de,(DETEMP)      ;1c60    ed 5b 04 5d     . [ . ] 
    ld hl,(HLTEMP)      ;1c64    2a 02 5d     * . ] 
    ret                 ;1c67    c9     . 
    ld hl,ROM_BASIC     ;1c68    21 7c 3c     ! | < 
    di                  ;1c6b    f3     . 
    push af             ;1c6c    f5     . 
    call IO_OFF         ;1c6d    cd 97 3c     . . < 
    ld a,(PORT255)      ;1c70    3a 16 5d     : . ] 
    and 127             ;1c73    e6 7f     . © 
    ld (PORT255),a      ;1c75    32 16 5d     2 . ] 
    out (255),a         ;1c78    d3 ff     . . 
    pop af              ;1c7a    f1     . 
    ret                 ;1c7b    c9     . 
    push af             ;1c7c    f5     . 
    call IO_OFF         ;1c7d    cd 97 3c     . . < 
    ld a,(PORT255)      ;1c80    3a 16 5d     : . ] 
    or #80              ;1c83    f6 80     . . 
    ld (PORT255),a      ;1c85    32 16 5d     2 . ] 
    out (255),a         ;1c88    d3 ff     . . 
    call IO_ON          ;1c8a    cd 9d 3c     . . < 
    pop af              ;1c8d    f1     . 
    ei                  ;1c8e    fb     . 
    ret                 ;1c8f    c9     . 
    out (255),a         ;1c90    d3 ff     . . 
    call IO_ON          ;1c92    cd 9d 3c     . . < 
    pop af              ;1c95    f1     . 
    ret                 ;1c96    c9     . 
    call F_BORDC        ;1c97    cd af 3c     . . < 
    out (252),a         ;1c9a    d3 fc     . . 
    ret                 ;1c9c    c9     . 
    call F_BORDC        ;1c9d    cd af 3c     . . < 
    or #80              ;1ca0    f6 80     . . 
    out (252),a         ;1ca2    d3 fc     . . 
    ret                 ;1ca4    c9     . 
    ld hl,FLAGS         ;1ca5    21 3b 5c     ! ; \ 
    bit 5,(hl)          ;1ca8    cb 6e     . n 
    jr z,$-2            ;1caa    28 fc     ( . 
    res 5,(hl)          ;1cac    cb ae     . . 
    ret                 ;1cae    c9     . 
    ld a,(BORDCR)       ;1caf    3a 48 5c     : H \ 
    and #38             ;1cb2    e6 38     . 8 
    rrca                ;1cb4    0f     . 
    rrca                ;1cb5    0f     . 
    rrca                ;1cb6    0f     . 
    ret                 ;1cb7    c9     . 
    di                  ;1cb8    f3     . 
    call IO_OFF         ;1cb9    cd 97 3c     . . < 
    ld a,127            ;1cbc    3e 7f     > © 
    jr $+7              ;1cbe    18 05     . . 
    call IO_OFF         ;1cc0    cd 97 3c     . . < 
    ld a,#FF            ;1cc3    3e ff     > . 
    out (255),a         ;1cc5    d3 ff     . . 
    ret                 ;1cc7    c9     . 
    call ROMBAS_Q       ;1cc8    cd c0 3c     . . < 
    lddr                ;1ccb    ed b8     . . 
    jr $-98             ;1ccd    18 9c     . . 
    call ROMBAS_Q       ;1ccf    cd c0 3c     . . < 
    ldir                ;1cd2    ed b0     . . 
    jr $-105            ;1cd4    18 95     . . 
    ld a,0              ;1cd6    3e 00     > . 
    nop                 ;1cd8    00     . 
    nop                 ;1cd9    00     . 
    in a,(#F7)          ;1cda    db f7     . . 
    cp #1E              ;1cdc    fe 1e     . . 
    jr nz,$+9           ;1cde    20 07       . 
    rst 8               ;1ce0    cf     . 
    ld sp,#013E         ;1ce1    31 3e 01     1 > . 
    ld (#5CEF),a        ;1ce4    32 ef 5c     2 . \ 
    ld hl,#5CB5         ;1ce7    21 b5 5c     ! . \ 
    ld bc,#00070        ;1cea    01 70 00     . p . 
    call #1655          ;1ced    cd 55 16     . U . 
    call ROMBETA_Q      ;1cf0    cd b8 3c     . . < 
    ld hl,65535         ;1cf3    21 ff ff     ! . . 
    ld (STEP_RATE),hl   ;1cf6    22 fa 5c     " . \ 
    ld (#5CFC),hl       ;1cf9    22 fc 5c     " . \ 
    ld (DSKTYPE),hl     ;1cfc    22 c8 5c     " . \ 
    ld (#5CCA),hl       ;1cff    22 ca 5c     " . \ 
    xor a               ;1d02    af     . 
    ld (DEFLTDRV),a     ;1d03    32 19 5d     2 . ] 
    ld (IF1VAR),a       ;1d06    32 18 5d     2 . ] 
    ld (D_ERRCOD),a     ;1d09    32 0f 5d     2 . ] 
    ld (RM_FPC),a       ;1d0c    32 1f 5d     2 . ] 
    ld a,#FF            ;1d0f    3e ff     > . 
    ld (ERR_NR),a       ;1d11    32 3a 5c     2 : \ 
    ld (PORT255),a      ;1d14    32 16 5d     2 . ] 
    ld (SV_DCFG),a      ;1d17    32 0c 5d     2 . ] 
    ld a,#D0            ;1d1a    3e d0     > . 
    out (31),a          ;1d1c    d3 1f     . . 
    ret                 ;1d1e    c9     . 
    ld a,#0D            ;1d1f    3e 0d     > . 
    push hl             ;1d21    e5     . 
    push bc             ;1d22    c5     . 
    ld b,a              ;1d23    47     G 
    ld a,(SV_DCFG)      ;1d24    3a 0c 5d     : . ] 
    or a                ;1d27    b7     . 
    push af             ;1d28    f5     . 
    ld a,b              ;1d29    78     x 
    call z,SAVECFGS     ;1d2a    cc 18 39     . . 9 
    call BAS_RST16      ;1d2d    cd 37 3d     . 7 = 
    pop af              ;1d30    f1     . 
    call z,LOADCFGS     ;1d31    cc 2b 39     . + 9 
    pop bc              ;1d34    c1     . 
    pop hl              ;1d35    e1     . 
    ret                 ;1d36    c9     . 
    ld hl,16            ;1d37    21 10 00     ! . . 
    jp CALLBAS          ;1d3a    c3 36 2e     . 6 . 
    ld a,11             ;1d3d    3e 0b     > . 
    out (31),a          ;1d3f    d3 1f     . . 
    push hl             ;1d41    e5     . 
    ld hl,#1F54         ;1d42    21 54 1f     ! T . 
    call CALLBAS        ;1d45    cd 36 2e     . 6 . 
    ld hl,#1B7B         ;1d48    21 7b 1b     ! { . 
    jp nc,CALLBAS       ;1d4b    d2 36 2e     . 6 . 
    pop hl              ;1d4e    e1     . 
    in a,(255)          ;1d4f    db ff     . . 
    and #80             ;1d51    e6 80     . . 
    jr z,$-18           ;1d53    28 ec     ( . 
    ret                 ;1d55    c9     . 
    ld a,11             ;1d56    3e 0b     > . 
    call FDC_CMD        ;1d58    cd 3f 3d     . ? = 
    ld de,0             ;1d5b    11 00 00     . . . 
    in a,(31)           ;1d5e    db 1f     . . 
    and 2               ;1d60    e6 02     . . 
    ld b,a              ;1d62    47     G 
    in a,(31)           ;1d63    db 1f     . . 
    and 2               ;1d65    e6 02     . . 
    cp b                ;1d67    b8     . 
    ret nz              ;1d68    c0     . 
    inc de              ;1d69    13     . 
    ld a,e              ;1d6a    7b     { 
    or d                ;1d6b    b2     . 
    jr nz,$-9           ;1d6c    20 f5       . 
    jp ER_NODISK        ;1d6e    c3 82 3e     . . > 
    ld a,(DEFLTDRV)     ;1d71    3a 19 5d     : . ] 
    ld (CURRDRIVE),a    ;1d74    32 f6 5c     2 . \ 
    ld hl,PORT255       ;1d77    21 16 5d     ! . ] 
    ld c,a              ;1d7a    4f     O 
    ld a,#3C            ;1d7b    3e 3c     > < 
    or c                ;1d7d    b1     . 
    out (255),a         ;1d7e    d3 ff     . . 
    ld (hl),a           ;1d80    77     w 
    call FT_STEPRT      ;1d81    cd b1 3d     . . = 
    and #80             ;1d84    e6 80     . . 
    jr z,$+29           ;1d86    28 1b     ( . 
    call DSK_DETC       ;1d88    cd 56 3d     . V = 
    call SCAN_SRATE     ;1d8b    cd bf 3d     . . = 
    call FT_DSKTYPE     ;1d8e    cd ba 3d     . . = 
    cp #FF              ;1d91    fe ff     . . 
    jr nz,$+16          ;1d93    20 0e       . 
    push hl             ;1d95    e5     . 
    call SCAN_NTRK      ;1d96    cd 77 30     . w 0 
    pop hl              ;1d99    e1     . 
    cp #50              ;1d9a    fe 50     . P 
    ld a,0              ;1d9c    3e 00     > . 
    jr nz,$+4           ;1d9e    20 02       . 
    ld a,#80            ;1da0    3e 80     > . 
    ld (hl),a           ;1da2    77     w 
    call CURRTRACK      ;1da3    cd e3 2e     . . . 
    ld a,#80            ;1da6    3e 80     > . 
    ld c,#FF            ;1da8    0e ff     . . 
    dec c               ;1daa    0d     . 
    jr nz,$-1           ;1dab    20 fd       . 
    dec a               ;1dad    3d     = 
    jr nz,$-6           ;1dae    20 f8       . 
    ret                 ;1db0    c9     . 
    ld de,STEP_RATE     ;1db1    11 fa 5c     . . \ 
    ld hl,(CURRDRIVE)   ;1db4    2a f6 5c     * . \ 
    add hl,de           ;1db7    19     . 
    ld a,(hl)           ;1db8    7e     ~ 
    ret                 ;1db9    c9     . 
    ld de,DSKTYPE       ;1dba    11 c8 5c     . . \ 
    jr $-9              ;1dbd    18 f5     . . 
    call FT_STEPRT      ;1dbf    cd b1 3d     . . = 
    ld b,%00001000      ;1dc2    06 08     . . 
    ld c,4              ;1dc4    0e 04     . . 
    ld (hl),b           ;1dc6    70     p 
    ld a,11             ;1dc7    3e 0b     > . 
    call FDC_CMD        ;1dc9    cd 3f 3d     . ? = 
    ld a,32             ;1dcc    3e 20     >   
    ld b,11             ;1dce    06 0b     . . 
    call SEEK_A         ;1dd0    cd ed 3d     . . = 
    ld b,(hl)           ;1dd3    46     F 
    ld a,1              ;1dd4    3e 01     > . 
    call SEEK_A         ;1dd6    cd ed 3d     . . = 
    in a,(31)           ;1dd9    db 1f     . . 
    and 4               ;1ddb    e6 04     . . 
    jr nz,$+11          ;1ddd    20 09       . 
    xor a               ;1ddf    af     . 
    call SEEK_A         ;1de0    cd ed 3d     . . = 
    in a,(31)           ;1de3    db 1f     . . 
    and 4               ;1de5    e6 04     . . 
    ret nz              ;1de7    c0     . 
    inc b               ;1de8    04     . 
    dec c               ;1de9    0d     . 
    ret z               ;1dea    c8     . 
    jr $-37             ;1deb    18 d9     . . 
    out (127),a         ;1ded    d3 7f     . © 
    ld a,b              ;1def    78     x 
    or 24               ;1df0    f6 18     . . 
    jp FDC_CMD          ;1df2    c3 3f 3d     . ? = 
    out (127),a         ;1df5    d3 7f     . © 
    push bc             ;1df7    c5     . 
    ld b,a              ;1df8    47     G 
    in a,(#3F )         ;1df9    db 3f     . ? 
    cp b                ;1dfb    b8     . 
    pop bc              ;1dfc    c1     . 
    push af             ;1dfd    f5     . 
    ld a,b              ;1dfe    78     x 
    or 24               ;1dff    f6 18     . . 
    call FDC_CMD        ;1e01    cd 3f 3d     . ? = 
    pop af              ;1e04    f1     . 
    ret z               ;1e05    c8     . 
    push bc             ;1e06    c5     . 
    call DELAY          ;1e07    cd a6 3d     . . = 
    pop bc              ;1e0a    c1     . 
    ret                 ;1e0b    c9     . 
    ld c,a              ;1e0c    4f     O 
    call SELSIDE0       ;1e0d    cd 98 30     . . 0 
    call FT_DSKTYPE     ;1e10    cd ba 3d     . . = 
    and 2               ;1e13    e6 02     . . 
    call nz,PHYSTRACK   ;1e15    c4 47 3e     . G > 
    push bc             ;1e18    c5     . 
    bit 7,(hl)          ;1e19    cb 7e     . ~ 
    jr z,$+17           ;1e1b    28 0f     ( . 
    bit 0,(hl)          ;1e1d    cb 46     . F 
    jr nz,$+13          ;1e1f    20 0b       . 
    in a,(#3F )         ;1e21    db 3f     . ? 
    cp c                ;1e23    b9     . 
    jr z,$+7            ;1e24    28 05     ( . 
    rlca                ;1e26    07     . 
    out (#3F ),a        ;1e27    d3 3f     . ? 
    ld a,c              ;1e29    79     y 
    rlca                ;1e2a    07     . 
    ld c,a              ;1e2b    4f     O 
    call FT_STEPRT      ;1e2c    cd b1 3d     . . = 
    ld b,a              ;1e2f    47     G 
    ld a,c              ;1e30    79     y 
    call TRACK_PA       ;1e31    cd f5 3d     . . = 
    pop bc              ;1e34    c1     . 
    ld a,c              ;1e35    79     y 
    out (#3F ),a        ;1e36    d3 3f     . ? 
    ld a,(NOTREADY)     ;1e38    3a cd 5c     : . \ 
    or a                ;1e3b    b7     . 
    ret z               ;1e3c    c8     . 
    ld b,3              ;1e3d    06 03     . . 
    ld a,#FF            ;1e3f    3e ff     > . 
    call DELAY01        ;1e41    cd a8 3d     . . = 
    djnz $-5            ;1e44    10 f9     . . 
    ret                 ;1e46    c9     . 
    ld a,c              ;1e47    79     y 
    or a                ;1e48    b7     . 
    rra                 ;1e49    1f     . 
    ld c,a              ;1e4a    4f     O 
    ret nc              ;1e4b    d0     . 
    jp SELSIDE1         ;1e4c    c3 a3 30     . . 0 
    call SELSIDE0       ;1e4f    cd 98 30     . . 0 
    in a,(31)           ;1e52    db 1f     . . 
    and #80             ;1e54    e6 80     . . 
    ld (NOTREADY),a     ;1e56    32 cd 5c     2 . \ 
    in a,(#3F )         ;1e59    db 3f     . ? 
    ld h,a              ;1e5b    67     g 
    call SEEK_A         ;1e5c    cd ed 3d     . . = 
    ld c,127            ;1e5f    0e 7f     . © 
    ld d,1              ;1e61    16 01     . . 
    ld a,#C0            ;1e63    3e c0     > . 
    out (31),a          ;1e65    d3 1f     . . 
    push bc             ;1e67    c5     . 
    ld b,3              ;1e68    06 03     . . 
    in a,(255)          ;1e6a    db ff     . . 
    and #C0             ;1e6c    e6 c0     . . 
    jr nz,$+31          ;1e6e    20 1d       . 
    inc de              ;1e70    13     . 
    ld a,e              ;1e71    7b     { 
    or d                ;1e72    b2     . 
    jr nz,$-9           ;1e73    20 f5       . 
    djnz $-11           ;1e75    10 f3     . . 
    pop bc              ;1e77    c1     . 
    ld a,#D0            ;1e78    3e d0     > . 
    out (31),a          ;1e7a    d3 1f     . . 
    ld a,(NODISK)       ;1e7c    3a d1 5c     : . \ 
    cp #FF              ;1e7f    fe ff     . . 
    ret z               ;1e81    c8     . 
    call ERROR_R        ;1e82    cd 9f 37     . . 7 
    ld a,#FF            ;1e85    3e ff     > . 
    ld (FLAGBUFF),a     ;1e87    32 17 5d     2 . ] 
    jp ER_NODISK01      ;1e8a    c3 8f 37     . . 7 
    pop bc              ;1e8d    c1     . 
    in h,(c)            ;1e8e    ed 60     . ` 
    in a,(255)          ;1e90    db ff     . . 
    and #C0             ;1e92    e6 c0     . . 
    jr z,$-4            ;1e94    28 fa     ( . 
    ret m               ;1e96    f8     . 
    in a,(127)          ;1e97    db 7f     . © 
    jr $-9              ;1e99    18 f5     . . 
    ld (STARTSECT),a    ;1e9b    32 ff 5c     2 . \ 
    ret                 ;1e9e    c9     . 
    ld (RWADDRESS),hl   ;1e9f    22 00 5d     " . ] 
    ret                 ;1ea2    c9     . 
    ld a,#A0            ;1ea3    3e a0     > . 
    jr $+4              ;1ea5    18 02     . . 
    ld a,#80            ;1ea7    3e 80     > . 
    ld (RW_CMD),a       ;1ea9    32 fe 5c     2 . \ 
    ld d,10             ;1eac    16 0a     . . 
    push de             ;1eae    d5     . 
    ld a,(STARTSECT)    ;1eaf    3a ff 5c     : . \ 
    inc a               ;1eb2    3c     < 
    out (95),a          ;1eb3    d3 5f     . _ 
    ld hl,(RWADDRESS)   ;1eb5    2a 00 5d     * . ] 
    ld c,127            ;1eb8    0e 7f     . © 
    ld a,(RW_CMD)       ;1eba    3a fe 5c     : . \ 
    out (31),a          ;1ebd    d3 1f     . . 
    cp #A0              ;1ebf    fe a0     . . 
    push af             ;1ec1    f5     . 
    call z,FDC_WDATA    ;1ec2    cc 50 3f     . P ? 
    pop af              ;1ec5    f1     . 
    call nz,FDC_RDATA   ;1ec6    c4 6b 3f     . k ? 
    pop de              ;1ec9    d1     . 
    in a,(31)           ;1eca    db 1f     . . 
    ld b,a              ;1ecc    47     G 
    and 127             ;1ecd    e6 7f     . © 
    ret z               ;1ecf    c8     . 
    ld hl,M_RDONLY      ;1ed0    21 7d 39     ! } 9 
    and #40             ;1ed3    e6 40     . @ 
    jr nz,$+13          ;1ed5    20 0b       . 
    ld a,b              ;1ed7    78     x 
    and 4               ;1ed8    e6 04     . . 
    jr z,$+92           ;1eda    28 5a     ( Z 
    dec d               ;1edc    15     . 
    jr nz,$-47          ;1edd    20 cf       . 
    ld hl,M_DSKERR      ;1edf    21 87 39     ! . 9 
    ld a,#D0            ;1ee2    3e d0     > . 
    out (31),a          ;1ee4    d3 1f     . . 
    ld a,b              ;1ee6    78     x 
    and 1               ;1ee7    e6 01     . . 
    jp nz,ER_NODISK     ;1ee9    c2 82 3e     . . > 
    in a,(#3F )         ;1eec    db 3f     . ? 
    or a                ;1eee    b7     . 
    jr nz,$+7           ;1eef    20 05       . 
    in a,(95)           ;1ef1    db 5f     . _ 
    cp 10               ;1ef3    fe 0a     . . 
    ret z               ;1ef5    c8     . 
    push hl             ;1ef6    e5     . 
    call BAS_CLS        ;1ef7    cd 33 2e     . 3 . 
    pop hl              ;1efa    e1     . 
    rst 24              ;1efb    df     . 
    ld hl,M_TRK         ;1efc    21 b8 39     ! . 9 
    rst 24              ;1eff    df     . 
    in a,(#3F )         ;1f00    db 3f     . ? 
    call PRINTN_A       ;1f02    cd 0c 39     . . 9 
    ld hl,M_SEC         ;1f05    21 bd 39     ! . 9 
    rst 24              ;1f08    df     . 
    in a,(95)           ;1f09    db 5f     . _ 
    call PRINTN_A       ;1f0b    cd 0c 39     . . 9 
    ld hl,M_RETRY       ;1f0e    21 a3 39     ! . 9 
    rst 24              ;1f11    df     . 
    call READKEY        ;1f12    cd 15 25     . . % 
    cp #49              ;1f15    fe 49     . I 
    ret z               ;1f17    c8     . 
    cp #52              ;1f18    fe 52     . R 
    jr z,$+17           ;1f1a    28 0f     ( . 
    cp #41              ;1f1c    fe 41     . A 
    jr nz,$-12          ;1f1e    20 f2       . 
    call ERROR_R        ;1f20    cd 9f 37     . . 7 
    ld a,#07            ;1f23    3e 07     > . 
    ld (D_ERRCOD),a     ;1f25    32 0f 5d     2 . ] 
    jp DSTM_RET         ;1f28    c3 70 21     . p ! 
    in a,(#3F)          ;1f2b    db 3f     . ? 
    call TRACK_LA       ;1f2d    cd 0c 3e     . . > 
    call LONGDELAY      ;1f30    cd 3d 3e     . = > 
    jp RDWRSECT01       ;1f33    c3 ac 3e     . . > 
    dec d               ;1f36    15     . 
    jp z,RDWRSECT04     ;1f37    ca df 3e     . . > 
    push de             ;1f3a    d5     . 
    call FT_STEPRT      ;1f3b    cd b1 3d     . . = 
    and 2               ;1f3e    e6 02     . . 
    jr nz,$+3           ;1f40    20 01       . 
    inc (hl)            ;1f42    34     4 
    call RESTORE        ;1f43    cd 3d 3d     . = = 
    ld a,(RWTRKID)      ;1f46    3a f5 5c     : . \ 
    call TRACK_LA       ;1f49    cd 0c 3e     . . > 
    pop de              ;1f4c    d1     . 
    jp RDWRSECT02       ;1f4d    c3 ae 3e     . . > 
    ld b,4              ;1f50    06 04     . . 
    in a,(255)          ;1f52    db ff     . . 
    and #C0             ;1f54    e6 c0     . . 
    jr nz,$+17          ;1f56    20 0f       . 
    inc de              ;1f58    13     . 
    ld a,e              ;1f59    7b     { 
    or d                ;1f5a    b2     . 
    jr nz,$-9           ;1f5b    20 f5       . 
    djnz $-11           ;1f5d    10 f3     . . 
    ret                 ;1f5f    c9     . 
    in a,(255)          ;1f60    db ff     . . 
    and #C0             ;1f62    e6 c0     . . 
    jr z,$-4            ;1f64    28 fa     ( . 
    ret m               ;1f66    f8     . 
    outi                ;1f67    ed a3     . . 
    jr $-9              ;1f69    18 f5     . . 
    ld b,4              ;1f6b    06 04     . . 
    in a,(255)          ;1f6d    db ff     . . 
    and #C0             ;1f6f    e6 c0     . . 
    jr nz,$+17          ;1f71    20 0f       . 
    inc de              ;1f73    13     . 
    ld a,e              ;1f74    7b     { 
    or d                ;1f75    b2     . 
    jr nz,$-9           ;1f76    20 f5       . 
    djnz $-11           ;1f78    10 f3     . . 
    ret                 ;1f7a    c9     . 
    in a,(255)          ;1f7b    db ff     . . 
    and #C0             ;1f7d    e6 c0     . . 
    jr z,$-4            ;1f7f    28 fa     ( . 
    ret m               ;1f81    f8     . 
    ini                 ;1f82    ed a2     . . 
    jr $-9              ;1f84    18 f5     . . 
    call NXTDIRSEC      ;1f86    cd 73 24     . s $ 
    ld a,(hl)           ;1f89    7e     ~ 
    or a                ;1f8a    b7     . 
    jp z,FILEENTRY01    ;1f8b    ca 2b 23     . + # 
    cp 1                ;1f8e    fe 01     . . 
    call z,ADDHL16      ;1f90    cc 6e 24     . n $ 
    ret nz              ;1f93    c0     . 
    jr $-14             ;1f94    18 f0     . . 
    ld a,#AA            ;1f96    3e aa     > . 
    ld (FLAGBUFF),a     ;1f98    32 17 5d     2 . ] 
    xor a               ;1f9b    af     . 
    jr $+4              ;1f9c    18 02     . . 
    ld a,#FF            ;1f9e    3e ff     > . 
    ld (FLAGRW),a       ;1fa0    32 ce 5c     2 . \ 
    ld de,9             ;1fa3    11 09 00     . . . 
    ld b,1              ;1fa6    06 01     . . 
    ld hl,BUFFER        ;1fa8    21 00 5b     ! . [ 
    jp LDSVBUFF02       ;1fab    c3 14 2f     . . / 
    push hl             ;1fae    e5     . 
    ld de,(RWSECID)     ;1faf    ed 5b f4 5c     . [ . \ 
    call LDSVBUFF01     ;1fb3    cd a6 3f     . . ? 
    ld a,(VAR_C_L)      ;1fb6    3a db 5c     : . \ 
    pop de              ;1fb9    d1     . 
    or a                ;1fba    b7     . 
    jr z,$-37           ;1fbb    28 d9     ( . 
    ld c,a              ;1fbd    4f     O 
    ld hl,BUFFER        ;1fbe    21 00 5b     ! . [ 
    ldir                ;1fc1    ed b0     . . 
    jr $-45             ;1fc3    18 d1     . . 

;------------------------------------------------------------------------------
; Mirror (#1FC5/8133) of table of DOS statement codes (#3FC5/16325)
;------------------------------------------------------------------------------
    defb #CF            ;       CAT
    defb #2A            ;       *
    defb #D0            ;       FORMAT
    defb #D1            ;       MOVE
    defb #E6            ;       NEW
    defb #D2            ;       ERASE
    defb #EF            ;       LOAD
    defb #F8            ;       SAVE
    defb #FE            ;       RETURN
    defb #BE            ;       PEEK
    defb #F4            ;       POKE
    defb #D5            ;       MERGE
    defb #F7            ;       RUN
    defb #D3            ;       OPEN #
    defb #D4            ;       CLOSE #
    defb #FF            ;       COPY
    defb #34            ;       4
    defb #EC            ;       GO TO
    defb #38            ;       8

;------------------------------------------------------------------------------
; Mirror (#1FD8/8152) of table of DOS statement routine addresses (#3FD8/16344)
;------------------------------------------------------------------------------
    defw DS_CAT         ;#23B2 
    defw DS_DRV         ;#24A1 
    defw DS_FORMAT      ;#2F6F 
    defw DS_MOVE        ;#27FF 
    defw DS_NEW         ;#24B7 
    defw DS_ERASE       ;#272B 
    defw DS_LOAD        ;#294C 
    defw DS_SAVE        ;#2B7A 
    defw DS_RETURN      ;#2D94 
    defw DS_PEEK        ;#2A73 
    defw DS_POKE        ;#2A77 
    defw DS_MERGE       ;#2A7F 
    defw DS_RUN         ;#2DDF 
    defw DS_OPEN        ;#3213 
    defw DS_CLOSE       ;#36C7 
    defw DS_COPY        ;#2645 
    defw DS_40          ;#393C 
    defw DS_GOTO        ;#3AD0 
    defw DS_80          ;#3953 

;-----------------------------------------------------------------------------
; Unused bytes (#1FFE/8190)
;-----------------------------------------------------------------------------
    defb #FF,#FF

;##############################################################################
; Disassembly listing - part 2
; Second mirrored page of CAS interface ROM (#2000-#3FFF/8192-16383). Most of 
;DOS routines are accessed here.
; The 16360-16615/#3C00-#3CFF area is watched by the disk interface and is
;visible even when BASIC ROM is enabled.
;##############################################################################

;------------------------------------------------------------------------------
; #2000-#201B (8192-8219) is a mirror of #0000-#001B (0-27) area where RESET,
;RST 16 and RST 24 can be found. 
;------------------------------------------------------------------------------
    ld d,e
    ld de,65535
    ld a,#07
    jr $+3
    nop
    out (254),a
    ld a,#3F 
    jr $+6
    nop
    jp PRNCHR01
    ld i,a
    jp RESET03
    jp PRNSTR01

;------------------------------------------------------------------------------
; RESET03 (#201B/8219)
; RESET routine started from the first ROM page continues here. There are 
;jump instructions to skip restart and NMI routines mirrored from first page.
;------------------------------------------------------------------------------
RESET03                 ;#201B
    nop                 ;       Do nothing.    
    nop
    nop
    jr RESET04          ;#2024  Skip page 1 routine.

;------------------------------------------------------------------------------
; #2020-#2024 (8224-8227) is mirror of #0020-#0023 (32-35) routine 
;(RST 32 - SAVE_HL). 
;------------------------------------------------------------------------------
    ld (HLTEMP),hl      ;       Store content of HL into DOS variable.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; RESET04 (#2024/8228)
; Part of RESET routine. RESET03 (#201B/8219) continues here.
;------------------------------------------------------------------------------
RESET04                 ;#2024
    ld h,d              ;       HL=address of the last byte of memory
    ld l,e              ;       addressable by Z80 CPU.
    jr RESET05          ;#202B  Skip page 1 routine.

;------------------------------------------------------------------------------
; #2028-#202A(8232-8234) is mirror of #0028-#002A (40-42) routine
;(RST #40).
;------------------------------------------------------------------------------
    jp SEL_CHINFO       ;#33B7

;------------------------------------------------------------------------------
; RESET05 (#202B/8235)
; Part of RESET routine. RESET 04 (#2024/8228) continues here.
;------------------------------------------------------------------------------
RESET05                 ;#202B
; Perform very simple RAM test.
    ld (hl),2           ;       Fill RAM with 2.
    dec hl              ;       Decrement pointer.
    cp h                ;       Repeat until H=63 (#3F). This happens when 
    jr nz,RESET05       ;       HL=#3FFF/16383, i.e. ROM is reached.

RESET06                 ;#2031
    or a                ;       Reset C flag.
    sbc hl,de           ;       HL=HL-#FFFF followed by HL=HL+#FFFF. C flag
    add hl,de           ;       is 0 only if HL=#FFFF.
    inc hl              ;       Increment pointer to next byte.
    jr nc,RESET07       ;       Exit loop if last byte (#FFFF/65535).
    dec (hl)            ;       Decrement value stored at (HL). Expected result
    jr z,RESET07        ;       is 1; exit loop if it is 0.
    dec (hl)            ;       Decrement again, now result must be 0. Reenter
    jr z,RESET06        ;#2031  loop if result is 0.

RESET07                 ;#203E
; Prepare UDG area and initialize some BASIC system variables.
    dec hl              ;       HL=address of last valid byte of RAM.
    ld (P_RAMT),hl      ;       Assign this address to BASIC system variable.
    ld de,16047         ;       Address of character bitmap table of BASIC ROM 
                        ;       that points to last byte of U character (at 
                        ;       #3EAF/16047).
    ld bc,168           ;       168 bytes will be copied.
    ld a,e              ;       A=175.
    ex de,hl            ;       DE=last byte of RAM and HL=16047.
    ld sp,24576         ;       Temporary stack location is #6000/24576.
    call LDDR_BAS       ;#3CC8  Copy downwards, so  destination address will
    ex de,hl            ;       point before the first byte of UDG "A".
    inc hl              ;       Increment pointer to the first byte of UDG "A".
    ld (UDG),hl         ;       This is the start of UDG area.
    dec hl              ;       Adjust pointer for one byte below UDG area.
    ld bc,#1E40         ;       Initialize RASP with 64 (#40) and PIP with 30 
    ld (RASP),bc        ;       (#1E) to make key click louder than default.
    ld (RAMTOP),hl      ;       Assign value to RAMTOP.
    ld hl,15360         ;       Character bitmap address (15616) minus 256.
    jr RESET08          ;#2069  Skip unused byte and NMI routine mirror.

;------------------------------------------------------------------------------
    defb #FF           ;        Unused byte.
;------------------------------------------------------------------------------
; #2066-#2068(8294-8296) is mirror of 0x0066-0x0068 (102-104) routine (NMI).
;------------------------------------------------------------------------------
    jp NMI01            ;#39DA 

;------------------------------------------------------------------------------
; RESET08 (#2069/8297)
; Part of RESET routine. RESET05 (#202B/8235) continues here.
;------------------------------------------------------------------------------
RESET08                 ;#2069
; Prepare top of RAM, including Z80 stack.
    ld (CHARS),hl       ;       Set address of character bitmap models.
    ld hl,(RAMTOP)      ;       Fetch top of RAM address.
    ld (hl),#3E         ;       Put end marker (#3E) in GOSUB stack.
    dec hl              ;       Move one position down and set stack pointer
    ld sp,hl            ;       address.
    dec hl              ;       The BASIC error returning address will be 
    dec hl              ;       stacked at address pointed by ERR_SP.
    ld (ERR_SP),hl
    ld de,#1303         ;       Put MAIN-4 BASIC routine address (#1303/4867) 
    push de             ;       onto stack.
    im 1                ;       Spectrum/TK90X uses interrupt mode 1.
    ld iy,ERR_NR        ;       IY points to ERR_NR.
; Prepare memory used by BASIC.
    ld hl,CHANSCOPY     ;       Channel information area starts at #5CB6/23734
    ld (CHANS),hl       ;       (but is moved by INITVARS afterwards).
    ld de,#15AF         ;       Source of channel informations at BASIC ROM.
    ld bc,21            ;       There are 21 bytes of data to copy.
    ex de,hl            ;       Swap source and destination address.
    call LDIR_BAS       ;#3CCF  Copy data to channel information area.
    ex de,hl            ;       DE=address after channel information area.
    dec hl              ;       The pointer for DATA is placed before the start
    ld (DATADD),hl      ;       of BASIC program area.
    inc hl              ;       Advance pointer one position to define BASIC 
    ld (PROG),hl        ;       program area (it's empty) and variable area.
    ld (VARS),hl
    ld (hl),#80         ;       Put marker for end of BASIC variable area.
    inc hl              ;       Advance pointer one position, set start of
    ld (E_LINE),hl      ;       BASIC line editor area and fill it with only 
    ld (hl),#0D         ;       one 'enter' (#0D/13) character.
    inc hl              ;       Advance pointer again and put the last 
    ld (hl),#80         ;       separator mark (#80/128).
    inc hl              ;       Advance pointer once more and set memory 
    ld (WORKSP),hl      ;       separation variables. The BASIC workspace and 
    ld (STKBOT),hl      ;       calculator stack are empty.
    ld (STKEND),hl
    ld a,%00111000      ;       Attributes: FLASH 0, BRIGHT 0, PAPER 7, INK 0.
    ld (ATTR_P),a       ;       Set permanent and temporary colour attributes 
    ld (ATTR_T),a       ;       for upper screen lines.
    ld (BORDCR),a       ;       Same attributes for lower screen lines.
    ld hl,#0523         ;       Initialize keyboard system variables REPDEL 
    ld (REPDEL),hl      ;       (#23/35), REPPER (#05/5),
    dec (iy-58)         ;       KSTATE (#FF/255)
    dec (iy-54)         ;       and KSTATE+4 (#FF/255).
    ld hl,#15C6         ;       Copy 14 bytes of BASIC ROM starting from #15C6/
    ld de,STRMS         ;       5574, containing data of stream -3 (#FD) to
    ld bc,14            ;       stream 3 (#03). Streams 4-15 stay closed.
    call LDIR_BAS       ;#3CCF
    set 1,(iy+1)        ;       Raise bit 1 of FLAGS ('using printer') and 
    ld hl,#0EDF         ;       clear printer buffer calling CLEAR-PRB routine 
    call CALLBAS        ;#2E36  (#0EDF/3807) of BASIC ROM.
    ld hl,DF_SZ         ;       Set lower screen lines to the smaller size 
    ld (hl),2           ;       (2 lines).
    ld hl,#128B         ;       Put address of BASIC ROM routine onto stack to
    push hl             ;       enable printing of Spectrum/TK90X logo after 
                        ;       return to BASIC monitor.
    ld a,#AA            ;       Flag #AA instructs DOS_CLI02 to execute "boot" 
    ld (BUFFER),a       ;       BASIC program.
    jp RESET09          ;#3C41  Jump to the last part or RESET routine.

;------------------------------------------------------------------------------
; Subroutine: EXECute BASic
; Address: #20F1/8433
; Prepare to run BASIC program saved in autostart mode ('SAVE <n$>LINE <l>') or 
;to return to BASIC editor.
; Called by: DS_LOAD, DS_RUN.
;------------------------------------------------------------------------------
EXEC_BAS                ;#20F1
    call IF1VSWP        ;#318C  Restore Interface 1 system variables.
    call RST_ERRSP      ;#21D5  Restore ERR_SP to previous value.
    call BAS_CLS        ;#2E33  Clear screen.
    ld hl,(E_LINE)      ;       HL=address of line editor memory.
    inc hl              ;       The 2 bytes after BASIC variables hold 
    ld e,(hl)           ;       the number of line to run in autostart mode
    inc hl              ;       (i.e. saved with 'SAVE <n$>LINE <l>').
    ld d,(hl)           ;       DE=autostart line of BASIC program.
    ld a,d    
    or e    
    ex de,hl    
    jr z,EXEC_BAS01     ;#210A  Jump forward if line is 0.
    xor a               ;       Otherwise, assign flag=0 (run BASIC).
    ld (LDPKEXEC),a

EXEC_BAS01              ;#210A
    ld (NEWPPC),hl      ;       Assing value of line to go to.
    xor a               ;       First statement of that line will be executed.
    ld (NSPPC),a
    ld hl,#16B0         ;       Call 'SET-MIN' BASIC ROM subroutine to clear 
    call CALLBAS        ;#2E36  editor, calculator stack and workspace.
    ld hl,(PROG)        ;       Place pointer for DATA statement one position 
    dec hl              ;       before BASIC program area.
    ld (DATADD),hl
    ld hl,EXEC_BAS02    ;#3C21  Routine continues in the area watched by
                        ;       Beta interface and thus visible even when DOS 
                        ;       ROM is not selected.
    call CALLBAS        ;#2E36  Use CALLBAS to select BASIC ROM before
                        ;       executing JUMP.

;------------------------------------------------------------------------------
; DOS_BASIC02 (#2124/8484)
; Part of DOS_BASIC routine. DOS_BASIC01 (#3C30/15408) continues here.
;------------------------------------------------------------------------------
DOS_BASIC02             ;#2124 
    call IF1VSWP        ;#318C  Save Interface 1 system variables.
    ld a,#FF            ;       Set DOSMODE flag as 'BASIC mode'.
    ld (DOSMODE),a
    xor a               ;       Reset this DOS system variable.
    ld (ZEROVAR),a
    ld a,#AA
    ld (FLAGBUFF),a
    ld hl,BASDOSRET     ;#21A4  Assign return address after execution of DOS
    ld (DOS_RET),hl     ;       statement.
    ld hl,0             ;       Save current stack pointer value before 
    add hl,sp           ;       modifying it.
    ld (OLDSP),hl
    dec hl              ;       Decrement stack pointer twice.
    dec hl
    ld sp,hl   
    call DEF_ERRSP      ;#21C0  Save old ERR_SP value and define new value.
;
; The line after USR 15360 must be ' REM : <DOS statement>'. The following 
;part will check syntax.
;
    ld hl,(CH_ADD)      ;       Fetch current cursor address.

DOS_BASIC03             ;#214B
    call ENDLINE        ;#2164  Check for end of line marker.

DOS_BASIC04             ;#214E
    jp z,DSTM_RET       ;#2170  Finish if such end of marker was found.
    cp 234              ;       Compare character from current position with 
                        ;       'REM' token.
    inc hl              ;       Advance cursor position but keep CH_ADD.
    jr nz,DOS_BASIC03   ;#214B  Retry if 'REM' was not found.
    call ENDLINE        ;#2164  Check for end of line marker.
    jr z,DOS_BASIC04    ;#214E  Finish if such end of marker was found (first
                        ;       jump to DOS_BASIC04 and next to DSTM_RET).
    cp 58               ;       Finish if ':' character was not found.
    jp nz,DSTM_RET      ;#2170 
    inc hl              ;       Advance cursor.
    jp DOSMAIN          ;#2296  Jump the to the main DOS interpreter.

;------------------------------------------------------------------------------
; Subroutine: END LINE
; Address: #2164/8548
; Look for end of line marker in the command line. 
; Input:  HL=pointer for the command line.
; Output: Z flag=1 if end of line was reached;
;         A=character fetched from current cursor position.
; Called by: DOS_BASIC02.
;------------------------------------------------------------------------------
ENDLINE                 ;#2164
    ld a,(hl)           ;       Fetch character.
    cp #0D              ;       Return with ZERO=1 if character is 'enter' (end 
    ret z               ;       of line marker).
    cp #80              ;       Return with ZERO=1 if character is #80 (end of 
    ret z               ;       program marker).
    or a                ;       Z flag=0.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; DIR_RET01 (#216D/8557)
; Part of DIR_RET (#24E6/9446). 
;------------------------------------------------------------------------------
DIR_RET01               ;#216D
    call WRT_BUFFER     ;#2EF0  Write directory entry and return do DOS 
                        ;       interpreter.

;==============================================================================
; Routine: Dos STateMent RETurn
; Address: #2170/8560
; Return address after execution of DOS statement.
; Called by: DOS_BASIC02, DOSMAIN, FILEENTRY01, ID_TYPE, DS_DRV, ERASE_ENFL, 
;COPYALL, DS_COPY, DS_ERASE, DS_MOVE, DS_LOAD, DS_MERGE, ER_NOSPACE, ERROR_RET,
;DS_RUN, DS_FORMAT, DS_OPEN, DS_CLOSE, DS_40, RDWRSECT07.
;==============================================================================
DSTM_RET                ;#2170
    ld a,#FF            ;       Set flag to not save disk configuration sector 
    ld (SV_DCFG),a      ;       stored in the printer buffer (see PRNCHR01).
    call BAS_SETW       ;#2DFB  Clear workspace if neccessary.
    call IF1VSWP        ;#318C  Save Interface 1 system variables.
    ld hl,FLAGBUFF      ;       Check (FLAGBUFF) flag.
    ld a,(hl)    
    or a    
    ld (hl),#AA         ;       Assign new flag value #AA.
    jr nz,DSTM_RET01    ;#2187  Jump forward if flag was nonzero, otherwise
    call LOADBUFF       ;#3F96  load printer buffer contents from disk.

DSTM_RET01              ;#2187
    ld hl,RM_FPC        ;       Check value of RM_FPC flag.
    ld a,(hl)    
    or a    
    ld (hl),0           ;       Reset flag.
    jr nz,DSTM_RET02    ;#2196  Jump forward if flag was nonzero.
    call BAS_RMFP       ;#2EB9  Otherwise, remove numeric constants from line
    call FET_ENTER      ;#21B5  and advance cursor until end of line (Enter).

DSTM_RET02              ;#2196
    ld sp,(OLDSP)       ;       Assign previous value to stack pointer.
    ld hl,(DOS_RET)     ;       Fetch return address.
    ld bc,(D_ERRCOD)    ;       BC=DOS error code, return value for 'USR 
    ld b,0              ;       15363' function called by BASIC monitor.
    jp (hl)             ;       Jump to return address (BASDOSRET/DOS_CLI03).

;==============================================================================
; Routine: BASic DOS RETurn
; Address: #21A4/8612
; Return address after execution of DOS statement in BASIC interface mode.
;This routine returns to BASIC interpreter. If an error is detected, jump to
;BASIC error handler.
; Called by: DOS_BASIC02.
;==============================================================================
BASDOSRET               ;#21A4
    call RST_ERRSP      ;#21D5  Restore ERR_SP.
    bit 7,(iy+0)        ;       Finish if bit 7 of (ERR_NR) is 1 because error 
    ret nz              ;       number is #FF ("0 - OK"), thus no real error 
                        ;       ocurred.
    ld de,ROM_BASIC     ;#3C7C  Address of routine that selects BASIC ROM.
    ld sp,(ERR_SP)      ;       Stack pointer will point to the BASIC error 
                        ;       handler.
    push de             ;       Jump to routine that select BASIC ROM before 
    ret                 ;       executing error handler.

;------------------------------------------------------------------------------
; Subroutine: FETch ENTER
; Address: #21B5/8629
; Advance cursor position (CH_ADD) until 'enter' character is found. Place
;cursor at the end of line.
; Called by: DSTM_RET.
;------------------------------------------------------------------------------
FET_ENTER               ;#21B5
    call BAS_GETCHR     ;#2E26  Get character from current cursor position.
    cp #0D              ;       Return if 'Enter' was found.
    ret z    
    call BAS_NXTCHR     ;#2ECB  Otherwise, advance cursor to next character
    jr FET_ENTER        ;#21B5  and try again.

;------------------------------------------------------------------------------
; Subroutine: DEFine ERR_SP
; Address: #21C0/8640
; Define new value of ERR_SP, valid during DOS operation. Any error will be
;directed to DOS instead BASIC monitor.
; Called by: DOS_BASIC, DOS_CLI02.
;------------------------------------------------------------------------------
DEF_ERRSP               ;#21C0
    ld hl,(ERR_SP)      ;       Save current value of ERR_SP to DOS system
    ld (ERRSPTMP),hl    ;       variable.
    ld hl,(OLDSP)       ;       New value of ERR_SP will be (OLDSP)-2.
    dec hl    
    dec hl    
    ld (ERR_SP),hl
    ld de,DOSERROR      ;#3C15  Put DOSERROR into stack to be the new return
    ld (hl),e           ;       address from error status. Its address is
    inc hl              ;       within range watched by Beta interface, thus
    ld (hl),d           ;       visible even when DOS ROM is disabled.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: ReSTore ERR_SP
; Address: #21D5/8661
; Restore saved value of ERR_SP.
; Called by: EXEC_BAS, BASDOSRET, DS_RETURN.
;------------------------------------------------------------------------------
RST_ERRSP               ;#21D5
    ld hl,(ERRSPTMP)    ;       Fetch old value of ERR_SP.
    ld (ERR_SP),hl      ;       Restore ERR_SP into previous state.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; DOS_CLI02 (#21DC/8668)
; Part of DOS_CLI routine. DOS_CLI01 (#3C49/15433) continues here.  
;------------------------------------------------------------------------------
DOS_CLI02               ;#21DC
    ld hl,0             ;       Reset ZEROVAR (it is always 0) and SRCDRIVE 
    ld (ZEROVAR),hl     ;       (drive 0 or "A").
    add hl,sp           ;       Save stack pointer value before modifing it.
    ld (OLDSP),hl
    dec hl
    dec hl
    ld sp,hl            ;       Decrement SP by two position.
    call DEF_ERRSP      ;#21C0  Define new value for ERR_SP.
    ld hl,FLAGBUFF      ;       Fetch value of (FLAGBUFF) and check if is equal
    ld a,(hl)           ;       to #AA.
    cp #AA
    ld a,0              ;       Set DOS error code 0, no error ocurred so far.
    ld (D_ERRCOD),a
    jp z,DOS_CLI03      ;#225D  Jump to line editor if (FLAGBUFF)=#AA.
    ld (hl),#AA         ;       Assign #AA to (FLAGBUFF).
    call BAS_CLS        ;#2E33  Clear screen.
    call OPEN_S         ;#2E22  Open channel "S", any printing will be directed
                        ;       to the main screen.
    ld hl,M_LOGO        ;#22EA  Print CAS initial logo.
    rst 24
    ld a,(BUFFER)       ;       (BUFFER)=#AA only after a computer reset (see 
    cp #AA              ;       RESET08).
    jr nz,DOS_CLI03     ;#225D  Jump to enter line editor mode if #AA was not 
                        ;       found; otherwise, execute "boot" program.
;------------------------------------------------------------------------------
; Routine: RUN BOOT 
; Address: #220D/8717
; Put 'RUN "boot"' statement into line editor and execute it. This entry point 
;is used by LOADARG (#29A9/10665).
;------------------------------------------------------------------------------
RUNBOOT                 ;#220D
    ld hl,(E_LINE)      ;       HL=address of line editor memory.
    ld a,#FE            ;       Set #FE flag to supress any error message being
    ld (CLR_WSP),a      ;       printed on screen. This prevents any message
                        ;       arising from disk without "boot" program in it.
    ld (hl),#F7         ;       Put 'RUN', a BASIC token.
    inc hl              ;       Advance cursor.
    ld (hl),#22         ;       Put '"'.
    inc hl              ;       Advance cursor.
    ld (hl),#62         ;       Put 'b'.
    inc hl              ;       Advance cursor.
    ld (hl),#6F         ;       Put 'o'.
    inc hl              ;       Advance cursor.
    ld (hl),#6F         ;       Put 'o'.
    inc hl              ;       Advance cursor.
    ld (hl),#74         ;       Put 't'.
    inc hl              ;       Advance cursor.
    ld (hl),#22         ;       Put '"'.
    inc hl              ;       Advance cursor.
    ld (K_CUR),hl       ;       Place editor cursor after last quotation mark.
    ld (hl),#0D         ;       Put 'enter' there.
    inc hl              ;       Advance cursor.
    ld (hl),#80         ;       Put end separator in the next position.
    inc hl              ;       Advance cursor.
    ld (WORKSP),hl      ;       Set memory separator system variables to the 
    ld (STKBOT),hl      ;       end of line editor. Empty workspace and 
    ld (STKEND),hl      ;       calculator stack.
    set 3,(iy+1)        ;       Set bit 3 of FLAGS to select 'L' type cursor.
    jr DOS_CLI04        ;#227E  Jump to interpret and execute command line.

;------------------------------------------------------------------------------
; Subroutine: COPY 3 Bytes
; Address: #2242/8770
; Copy 3 bytes.
; Input: HL=source address.
;        DE=destination address.
; Called by DOS_CLI03, LOADLINE.
;------------------------------------------------------------------------------
COPY3B                  ;#2242
    ld b,3              ;       3 bytes will be copied.

COPY3B01                ;#2244
    ld a,(hl)           ;       Take byte from source.
    ld (de),a           ;       Copy to destination.
    inc hl              ;       Increment pointers.
    inc de    
    djnz COPY3B01       ;#2244  Repeat loop until all 3 bytes were copied.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: FLIP HLT
; Address: #224B/8779
; Send value to port 255 with alternating bit 3 (FDC HLT signal). Its purpose 
;is unknown.
; Input: A=last byte sent to port 255 (PORT255 system variable).
; Called by: DOS_CLI03.
;------------------------------------------------------------------------------
FLIPHLT                 ;#224B
    ld b,32             ;       Execute loop 32 times.

FLIPHLT01               ;#224D
    push bc             ;       Stack counter.
    xor %00001000       ;       Toggle bit 3 (FDC HLT signal) and send byte to
    out (255),a         ;       port 255.
    push af             ;       Stack last value sent to port 255.
    ld a,5              ;       Time constant for pause of 20485 T (5,7 ms).
    call DELAY01        ;#3DA8  Wait.
    pop af              ;       Unstack last value sent to port 255.
    pop bc              ;       Unstack counter.
    djnz FLIPHLT01      ;#224D  Repeat loop until end of counting.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; DOS_CLI03 (#225D/8797)
; Part of DOS_CLI routine. DOS_CLI02 (#21DC/8668) continues here. This is also
;the return point after execution of a DOS statement in CLI mode.
;------------------------------------------------------------------------------
DOS_CLI03               ;#225D
    ld hl,(OLDSP)       ;       Fetch old value of stack pointer.
    dec hl              ;       Decrement twice and assign it as the new stack 
    dec hl              ;       pointer value.
    ld sp,hl    
    call IF1VSWP        ;#318C  Restore Interface 1 system variables.
    call OPEN_K         ;#2E1C  Open channel "K", printing will be redirected 
                        ;       to the lower lines of screen.
    ld a,(PORT255)      ;       Get last value sent to port 255 and raise bits
    or %00000011        ;       0-1 to select slowest stepping motor rate.
    call FLIPHLT        ;#224B  Toggle FDC HLT bit 32 times.
    ld a,(PORT255)      ;       Get last value sent to port 255.
    call FLIPHLT        ;#224B  Toggle FDC HLT bit 32 times.
    xor a               ;       (DOSMODE)=#00 (CLI mode).    
    ld (DOSMODE),a
    call EDITLINE       ;#31C6  Wait for user input in the line editor.

;------------------------------------------------------------------------------
; DOS_CLI04 (#227E/8830)
; Part of DOS_CLI routine. RUNBOOT (#220D/8717) continues here.
;------------------------------------------------------------------------------
DOS_CLI04               ;#227E
    call BAS_CLSLOW     ;#2E40  Clear lower lines of screen.
    ld hl,DOS_CLI03     ;#225D  Define DOS_CLI03 as return address.
    ld (DOS_RET),hl
    xor a               ;       DOS error code 0, no error ocurred yet.
    ld (D_ERRCOD),a
    ld hl,(E_LINE)      ;       HL is the cursor of command line editor area.
    push hl             ;       Stack cursor address.
    ld de,ELINE_T       ;       Save 3 bytes of line editor to temporary area.
    call COPY3B         ;#2242
    pop hl              ;       Unstack cursor address.

;==============================================================================
; Routine: DOS MAIN
; Address: #2296/8854
; Main DOS command line interpreter. DOS_BASIC02 (#2124/8484) and DOS_CLI04
;(#227E/8830) continues here. Fetch DOS statement code from the first byte of 
;the line and look up it in the T_DSTMCOD table. Then, corresponding routine 
;address is fetched from T_DSTMADD table. Statement routine is executed twice, 
;first pass is syntax checking and second pass is the actual execution.
;==============================================================================
DOSMAIN                 ;#2296
    ld (DSTMADDR),hl    ;       Save interpreter cursor address into variable.
    ld a,(hl)           ;       Take statement code from line.
    ld b,a              ;       Save code temporarily in B register.
    and %10000000       ;       Check bit 7 (0 for *, 40 or 80 statements).
    ld a,b              ;       Fetch token code again.
    jr z,DOSMAIN01      ;#22A9  Jump forward and don't change current drive if 
    cp #FE              ;       bit 7 was 0 or if 'RETURN' token (#FE) was 
    jr z,DOSMAIN01      ;#22A9  found.
    push af             ;       Stack statement code.
    call SEL_DRIVE      ;#3D71  Select current drive.
    pop af              ;       Unstack statement code.

DOSMAIN01               ;#22A9
    ld hl,T_DSTMCOD     ;       HL=address of DOS statement code table.
    dec hl              ;       Go back one position.
    ld c,0              ;       C=(first statement)-1.

DOSMAIN02               ;#22AF
; This loop seeks for statement code in the look-up table.
    inc c               ;       Increment statement number.
    ld d,a              ;       Save statement code temporarily.
    ld a,19             ;       There are 19 statements to try.
    cp c                ;       Exit interpretation of line if statement number
    jp c,DSTM_RET       ;#2170  is greater than 19.
    ld a,d              ;       Restore statement code.
    inc hl              ;       Advance pointer to next table element.
    cp (hl)             ;       Retry loop until statement is found in table.
    jr nz,DOSMAIN02     ;#22AF  C=statement number (1-19).

; Set some DOS system variables.
    ld a,9              ;       Compare 9 bytes when seeking for a file.
    ld (CMP_SIZE),a
    xor a               ;       A=0.
    ld (D_ERRCOD),a     ;       Reset DOS error code (no error so far).
    ld (CODEARG),a      ;       No argument after 'LOAD <n$>CODE' statement.
    ld (LDPKEXEC),a     ;       Flag, 0='execute LOAD statement'.
    ld hl,FLAGS         ;       Reset bit 7 of FLAGS to activate syntax 
    res 7,(hl)          ;       checking mode.
    ld b,0              ;       Reset MSB of BC register pair.
    ld hl,T_DSTMADD     ;       Start address of routine address table.
    dec c               ;       Indexation of table is done by:
    sla c               ;       HL= HL+2*(C-1).
    add hl,bc    
    ld e,(hl)           ;       E=(HL), D=(HL+1).
    inc hl    
    ld d,(hl)           ;       DE=address of statement routine.
    ex de,hl            ;       HL=address of statement routine.
    push hl             ;       This address is stacked to be executed after
                        ;       syntax checking pass.
    ld de,STXCH_RET     ;#22E3  Set return address after first pass of
    push de             ;       statement routine.
    jp (hl)             ;       Jump to statement routine for the first pass.

;------------------------------------------------------------------------------
; Routine: STXCH_RET
; Address: #22E3/8931
; Return point after syntax checking when a DOS statement routine is executed
;for first time by DOSMAIN. Set bit 7 of FLAGS (syntax checking is done) and
;execute DOS statement again.
; Called by: DOSMAIN.
;------------------------------------------------------------------------------
STXCH_RET               ;#22E3
    ld hl,FLAGS         ;       Set bit 7 of FLAGS, signaling end of syntax 
    set 7,(hl)          ;       checking.
    pop hl              ;       Same as RET. Execute DOS statement.
    jp (hl)    

;==============================================================================
; Message: M_LOGO
; Address: #22EA/8938.
; Displayed after DOS initialization.
; +-----------------------------+
; |                             |
; |     *       DOS       *     |
; |                             |
; |       cas ltd. © 1986       |
; |                             |
;==============================================================================
M_LOGO                  ;#22EA
    defb #16,#01,#05    ;       'AT 1,5;'.
    defm "*"
    defm "       "      ;       7 spaces.
    defm "DOS"
    defm "       "      ;       7 spaces.
    defm "*"
    defb #0D,#0D        ;       'Enter', 'Enter'.
    defm "       "      ;       7 spaces.
    defm "cas ltd. "
    defb #7F            ;       'Copyright'.
    defm " 198"
    defb #B6            ;       "6"+#80 (end marker).

;------------------------------------------------------------------------------
; Unused message. Probably remaining of original Beta message.
;------------------------------------------------------------------------------
    defm "         "    ;       9 spaces.
    defb #16,#05,#0B    ;       'AT 5,11;'
    defm "      "       ;       6 spaces.
    defb #00            ;       End marker.
;==============================================================================

;-----------------------------------------------------------------------------
; FILEENTRY01 (#232B/9003). Part of FILEENTRY (#3F86/16262) subroutine.
; An end of directory marker has been found, so print number of free sectors
;and exit.
;-----------------------------------------------------------------------------
FILEENTRY01             ;#232B
    call READ_CS        ;#237F  Read disk configuration sector.
    call PRT_ENTER      ;#3D1F  Print 'Enter'.
    call PRT_ENTER      ;#3D1F  Print 'Enter'.
    ld bc,(BUFFER+CS_NFREE)
    call BAS_PRNTBC     ;#2E45  Print number of free sectors.
    ld hl,M_FREE        ;#3977  Print " Free".
    rst 24
;------------------------------------------------------------------------------
; ID_TYPE uses this path to return to DOS and saves one byte of RAM.
;------------------------------------------------------------------------------
ID_TYPE03               ;#233F
    jp DSTM_RET         ;#2170  Return to DOS interpreter.

;------------------------------------------------------------------------------
; Subroutine: PRINT if ERRor
; Address: #2342/9026
; Print error message if DOS is in CLI mode and CLR_WSP flag is not #FE. 
; Input:  HL=address of message;
;         A=DOS error code.
; Called by: ER_NOSPACE, ERROR_RET.
;------------------------------------------------------------------------------
PRINTERR                ;#2342
    push af             ;       Stack DOS error code.
    ld a,(CLR_WSP)      ;       Fetch flag stored in CLR_WSP.
    cp #FE              ;       Jump forward and print message if flag is not 
    jr nz,PRINTERR01    ;#234C  #FE.
    pop af              ;       Unstack DOS error code.
    ret                 ;       End of subroutine.

PRINTERR01              ;#234C
    pop af              ;       Unstack DOS error code and store into DOS
    ld (D_ERRCOD),a     ;       system variable.
    ld a,(DOSMODE)      ;       Fetch DOSMODE. 
    or a                ;       Print string pointed by HL if DOS is in CLI 
    call z,PRNSTR01     ;#377B  mode.
    ret                 ;       End of subroutine.
   
;------------------------------------------------------------------------------
; Error routine: NO FILE
; Address: #2358/9048
; Error raised when file was not found in the directory.
; Called by: DS_NEW, ERASE_ENFL, COPYALL, LOADARG, SEEKSTRM, DS_GOTO.
;------------------------------------------------------------------------------
ER_NOFILE               ;#2358
    ld hl,M_NOFILE      ;#39CD  Message "No File(s)".
    ld a,1              ;       DOS error code 1.
    jp DSTM_ERRET       ;#2CE5  Jump to error handler. 

;------------------------------------------------------------------------------
; Subroutine: READ Track 0, Sector 0
; Address: #2360/9056
; Read sector 0 from track 0 of disk and write to the printer buffer.
; Output: HL=23551;
;         (RWSECID)=1;
;         (RWTRKID)=0.
; Called by: DS_CAT, SEEKFILE.
;------------------------------------------------------------------------------
READT0S0                ;#2360
    xor a               ;       A=0, sector to be read.
    ld (TRK0SECT),a     ;       Next subroutine will read sector (TRK0SECT).

;------------------------------------------------------------------------------
; Subroutine: READ Track 0, Sector X
; Address: #2364/9060
; Read disk sector of track 0 and write to the printer buffer. The sector ID
;is fetched from TRK0SECT. The contents of printer buffer can be saved or not
;depending on FLAGBUFF value.
; Output: HL=23551;
;         (RWSECID)=next sector after the last read one;
;         (RWTRKID)=0.
; Called by: READT0S0, NXTDIRSEC, CP_ENTRY.
;------------------------------------------------------------------------------
READT0SX                ;#2364
    ld de,(TRK0SECT)    ;       Fetch sector number.
    ld d,0              ;       D=track 0.

;------------------------------------------------------------------------------
; READ_CS01 (#236A/9066)
; Entry point for READ_CS subroutine. If (FLAGBUFF) is not 0, save printer
;buffer to track 0/sector 9 of disk before it is overwritten.
;------------------------------------------------------------------------------
READ_CS01               ;#236A
    ld hl,FLAGBUFF      ;       Check if FLAGBUFF flag is 0 and reset it to
    xor a               ;       prevent further attempt to save printer buffer
    cp (hl)             ;       to disk.
    ld (hl),a
    jr z,READT0SX0_1    ;#2377  Skip subroutine that saves printer buffer if
                        ;       flag was zero.
    push de             ;       Stack sector/track values.
    call SAVEBUFF       ;#3F9E  Save printer buffer into track 0/sector 9.
    pop de              ;       Unstack sector/track values.

READT0SX0_1              ;#2377
    ld hl,BUFFER        ;       Start address where data will be written to.
    ld b,1              ;       1 sector will be read.
    jp RDSECTORS        ;#2EEA  Jump to read sector.

;------------------------------------------------------------------------------
; Subroutine: READ Configuration Sector
; Address: #237F/90
; Read configuration sector of disk (track 0, sector 8) and save to printer
;buffer (BUFFER). Previous contents of printer buffer can be saved or not 
;depending on FLAGBUFF value.
; Output: HL=23551;
;         (RWSECID)=9;
;         (RWTRKID)=0.
; Called by: ID_TYPE, COPYFILE, ERASEFILE, ERASEFILE, DS_MOVE, DIRFULL, 
;SAVEFILE.
;------------------------------------------------------------------------------
READ_CS                 ;#237F
    ld de,8         ;       D=track 0 and E=sector 8.
    jr READ_CS01        ;#236A  Jump backward to read disk.

;------------------------------------------------------------------------------
; Subroutine: ID TYPE
; Address: #2384/9092
; Read configuration sector of disk (see 'Format of Beta diskette'), check for 
;Beta ID byte and update current disk element of DSKTYPE array.
; Called by: DS_CAT, DS_NEW, COPYALL, DS_COPY, DS_MOVE, SEEKSTRM, USTK_FILE.
;------------------------------------------------------------------------------
ID_TYPE                 ;#2384
    call READ_CS        ;#237F  Read configuration sector and save into
    ld a,(BUFFER+CS_IDENT) ;    printer buffer.
    cp 16               ;       Jump if CS_IDENT byte of disk (Beta disk ID) 
    jr z,ID_TYPE01      ;#2394  is 16 to skip error handler; otherwise, print
    ld hl,M_DSKERR      ;#3987  error message (disk is not Beta).
    rst 24    
    jr ID_TYPE03        ;#233F  Return to DOS interpreter.

ID_TYPE01               ;#2394
    call FT_DSKTYPE     ;#3DBA  Fetch data of current disk type.
    res 0,(hl)          ;       Reset bits 0 (40 tracks) and 1 (single face).
    res 1,(hl)
    ld a,(BUFFER+CS_DTYPE)
    bit 0,a             ;       Fetch disk type and check number of tracks.
    jr nz,ID_TYPE02     ;#23A4  Jump if disk has 40 tracks; otherwise, set 
    set 0,(hl)          ;       bit 0 of current element of DSKTYPE array.

ID_TYPE02               ;#23A4
    bit 3,a             ;       Check number of sides.
    ret nz              ;       Return if disk has 1 side.
    set 1,(hl)          ;       Otherwise, set bit 1 of DSKTYPE array element.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: NOARG
; Address: #23AA/9130
; Test presence of argument in the line.
; Output: Z flag=1 (no argument after statement).
; Called by: DS_CAT, LOADARG, DS_FORMAT, DS_40 and DS_80.
;------------------------------------------------------------------------------
NOARG                   ;#23AA
    ld hl,(DSTMADDR)    ;       HL points to the statement.
    inc hl              ;       Advance to next byte.
    ld a,(hl)           ;       Compare byte with 'Enter' (line terminator).
    cp 13               ;       Raise Z flag if it is "Enter".
    ret                 ;       End of subroutine.

;==============================================================================
; DOS Statement: CAT 
; Address: #23B2/9138
; Show disk catalog. The contents of catalog can be redirected to a stream.
; Syntax:   CAT [<d$>]
;           CAT [#<s>,<d$>]
;  (d$=drive ID; s=stream ID)
; Example of screen output:
;  +--------------------------------+
;  |Title: DskLabel                 |
;  |5 File(s)                       |
;  |1 Del. File                     |
;  |                                |
;  |A:boot    <B>  1:Menu    <B> 16 |
;  |A:GameBas <B>  2:GameScrn<C> 27 |
;  |A:GameCode<C>120                |
;  |                                |
;  |1098 Free                       |
;  |                                |
;  |                                |
; ...                              ...
;  |                                |
;  |A>K                             |
;  +--------------------------------+
;==============================================================================
DS_CAT                  ;#23B2
    call NOARG          ;#23AA  Check presence of argument.
    ld bc,2             ;       Define stream #2 as default.
    ld (VAR_C),bc
    jr z,DS_CAT03       ;#23E9  Skip argument parsing if no argument found.
                        ;       Otherwise, evaluate stream and drive ID.
    cp "#"              ;       Argument other than "#" does not specify a 
    jr nz,DS_CAT01      ;#23DC  stream so this argument evaluation is skipped.
    ld (CH_ADD),hl      ;       Update position of line interpreter pointer.
    call GETARG_I       ;#2EA8  Evaluate numeric argument and put in (VAR_C).
    call BAS_GETCHR     ;#2E26  Move intepreter pointer to next char.
    cp #0D              ;       Jump forward if next character is 'Enter' (end 
    jr z,DS_CAT03       ;#23E9  of line).
    cp ","              ;       Character other than 'comma' raises syntax 
    jp nz,ER_SYNTX      ;#2DB3  error.
    call BAS_NXTCHR     ;#2ECB  Advance interpreter pointer to the next 
    call BAS_EEXP       ;#2E58  character and get string type argument.
    jr DS_CAT02         ;#23DF  Once drive ID has been fetched, skip next 
                        ;       instruction.
DS_CAT01                ;#23DC
; Evaluate drive ID for statement without stream specification.
    call GET1ARG_S      ;#2E7C  Get string with drive ID.

DS_CAT02                ;#23DF
; At this point, all arguments have been evaluated. Return if mode is syntax
;checking or execute command line.
    call SYN_CHCK       ;#2E0E  Return if DOS is in syntax checking mode.
    call BAS_STKFET     ;#2E4E  Get string data from stack: DE=address, BC=
                        ;       length.
    ex de,hl            ;       HL=string address.
    call GET_DRV        ;#2D1A  Change current drive accordingly to the
                        ;       argument entered in command line.
DS_CAT03                ;#23E9
    call SYN_CHCK       ;#2E0E  Return if DOS is in syntax checking mode (for
                        ;       no argument command).
    xor a               ;       Flag: #00=save disk configuration stored into 
    ld (SV_DCFG),a      ;       printer buffer (see PRNCHR01).
    call ID_TYPE        ;#2384  Get disk type.
    ld a,(VAR_C_L)      ;       Fetch current stream.

DS_CAT04                ;#23F6
    cp 2                ;       Clear screen if stream is 2 (channel "S").
    push af             ;       Stack stream ID.
    call z,BAS_CLS      ;#2E33  Clear screen.
    pop af              ;       Unstack stream ID.
    cp 17               ;       Raise syntax error condition if stream number 
    jp nc,ER_SYNTX      ;#2DB3  is greater than allowed value (>16).
    call BAS_OPEN       ;#2E1D  Open stream.

; Print disk catalog header
    ld hl,M_TITLE       ;#399C  Print "Title: ". 
    rst 24
    ld hl,BUFFER+CS_LABEL ;     Print disk label (end of string marker is in
    rst 24              ;       disk configuration sector).
    call PRT_ENTER      ;#3D1F  Print 'Enter'.
    ld a,(BUFFER+CS_NFILE) ;    A=(number of all files)-(number of erased  
    ld hl,BUFFER+CS_ERASF  ;    files), i.e., number of accessible files.
    sub (hl)
    push hl             ;       Stack address of erased files.
    call PRINTN_A       ;#390C  Print numeric value of A (number of accessible
    ld hl,M_FILE        ;#39D0  files.
    rst 24              ;       Print "File(s)".
    pop hl              ;       Unstack address of erased files.
    ld c,(hl)           ;       Fetch number of erased files and print it.
    call PRINTN_C       ;#390D  
    ld hl,M_DELFILE     ;#39C2  Print " Del. File".
    rst 24
    call READT0S0       ;#2360  Read start of directory into printer buffer.
    ld hl,BUFFER        ;       HL=start address of first entry.

; Print file informations. Each line begins with drive letter, followed by one
;colon and data of two files separeted by one colon. Printed file data are
;filename, file type ("<B>", "<C>", "<D>" or "<#>") and file size.

DS_CAT05                ;#242E
; Outer loop prints one line.
    call FILEENTRY      ;#3F86  Look for directory entry; exit statement if end
                        ;       of directory marker is found.
    call PRT_ENTER      ;#3D1F  Print 'Enter' to begin new line.
    ld a,(CURRDRIVE)    ;       Get current drive number and convert to drive 
    add a,"A"           ;       letter.
    rst 16              ;       Print driver letter.
    ld b,2              ;       Counter for 2 directory entries.

DS_CAT06                ;#243C
; Inner loop prints one entry for each pass.
    call FILEENTRY      ;#3F86  Look for directory entry; exit statement if end
                        ;       of directory marker is found.
    push bc             ;       Stack entry counter.
    ld a,":"            ;       Print colon.
    rst 16    
    push hl             ;       Stack entry address.
    call PR_FILENAM     ;#38FA  Print filename and file type.
    ld bc,13            ;       File size (number of sectors) is stored at 13th 
                        ;       byte of directory entry.
    pop hl              ;       Unstack entry address.
    push hl             ;       Stack entry address.
    add hl,bc           ;       Calculate address where file size is stored.
    ld c,(hl)           ;       C=file size.
    push bc             ;       Stack file size.
    ld a,c              ;       A=file size.
    ld b,2              ;       2 leading spaces for A<10.
    cp 10
    jr c,DS_CAT07       ;#2457  Skip next instruction if A<10.
    dec b               ;       1 leading space for A>=10.

DS_CAT07                ;#2457
    cp 100              ;       Don't print any leading space if A>=100.
    jr nc,DS_CAT09      ;#2460 

DS_CAT08                ;;#245B
    ld a,#20            ;       Print 1 or 2 leading spaces, depending on 
    rst 16              ;       numeric value.
    djnz DS_CAT08       ;#245B 

DS_CAT09                ;#2460
    pop bc              ;       Unstack file size.
    call BAS_PRNTBC     ;#2E45  Print file size.
    pop hl              ;       Unstack entry address.
    pop bc              ;       Unstack entry counter.
    ld de,16            ;       Advance directory entry pointer 16 positions.
    add hl,de    
    djnz DS_CAT06       ;#243C  Repeat until 2 entries were printed.
    jr DS_CAT05         ;#242E  Repeat to print next line.

;------------------------------------------------------------------------------
; Subroutine: ADD HL,16
; Address: #246E/9326
; HL=HL+16. Advance directory pointer to next entry (each directory entry has 
;size of 16 bytes).
; Input:  HL=directory entry address.
; Output: HL=next entry address;
;         DE=16.
; Called by: FILEENTRY.
;------------------------------------------------------------------------------
ADDHL16                 ;#246E
    ld de,16            ;       DE=16.
    add hl,de           ;       HL=HL+DE.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: NeXT DIRectory SECtor
; Address: #2473/9331
;　Check directory entry pointer position; if it is out of printer buffer area 
;(>23551), read next sector and place pointer to start of printer buffer.
; Input: HL=address of directory entry in the printer buffer area.
; Called by: SEEKFILE, FILEENTRY. 
;------------------------------------------------------------------------------
NXTDIRSEC               ;#2473
    push hl             ;       Save HL and BC.
    push bc    
    ld bc,#A400         ;       BC=-23552
    add hl,bc           ;       HL=HL-23552. 
    jr c,NXTDIRSEC01    ;#247E  Jump forward if HL<BC; otherwise, do nothing.
    pop bc              ;       Restore HL and BC.
    pop hl    
    ret                 ;       End of subroutine.

NXTDIRSEC01             ;#247E
    ld hl,TRK0SECT      ;       Increment sector number.
    inc (hl)    
    call READT0SX       ;#2364  Read sector. Data will be written into BUFFER.
    pop bc              ;       Restore BC and HL.
    pop hl    
    ld hl,BUFFER        ;       HL points to start of BUFFER.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: DRIVE NUMber
; Address: #248B/9355
; Convert drive letter to drive number. Out of range value raises error 
;condition.
; Input:  A=drive letter ("A"-"D" or "a"-"d").
; Output: A=drive number (0-3).
; Called by: DS_DRV, GET_DRV.
;------------------------------------------------------------------------------
DRIVENUM                ;#248B
    and %11011111       ;       Convert letter to uppercase and reset C flag.
    sbc a,65            ;       A=A-"A". A=number of drive (0-3)
    jp c,ER_SYNTX       ;#2DB3  Negative value raises syntax error.
    cp 4                ;       Value greater than 3 raises syntax error.
    jp nc,ER_SYNTX      ;#2DB3 
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: UnSTacK STRing
; Address: #2498/9368
; Take string data from top of calculator stack. Null length string interrupts
;this subroutine and raises syntax error (actually this code considers B=C as 
;error, so length such as #0101, #0202, ..., are also illegal).
; Input:  Top of calculator stack=string data.
; Output: DE=string start address;
;         BC=string length.
; Called by: DS_DRV, GET_FNAME.
;------------------------------------------------------------------------------
USTK_STR                ;#2498
    call BAS_STKFET     ;#2E4E  Take string data from top of calculator stack.
    ld a,c              ;       Raise syntax error condition if B=C (it is 
    cp b                ;       supposed B and C are 0). Instead 'cp b', 'or b'
    jp z,ER_SYNTX       ;#2DB3  instruction is more appropriate here.
    ret                 ;       End of subroutine.
    
;==============================================================================
; DOS Statement: * 
; Address: #24A1/9377
; Select current drive.
; Syntax:   *<d$>   
; (d$=drive ID).
;==============================================================================
DS_DRV                  ;#24A1
    call GET1ARG_S      ;#2E7C  Unstack argument from calculator stack.
    call SYN_CHCK       ;#2E0E  Return if DOS is in syntax checking mode.
    call USTK_STR       ;#2498  Fetch string data from calculator stack.
    ld a,(de)           ;       Fetch first letter of the string.
    call DRIVENUM       ;#248B  Convert drive letter to drive number and save
    ld (DEFLTDRV),a     ;       into DOS system variable.
    call SEL_DRIVE01    ;#3D74  Change current drive.
    jp DSTM_RET         ;#2170  Return to DOS interpreter.

;==============================================================================
; DOS Statement: NEW 
; Address: #24B7/9399
; Rename file.
; Syntax:   NEW <n$>,<o$>
;           NEW <n$>,<o$>CODE
;           NEW <n$>,<o$>DATA
;           NEW <n$>,<o$>#
;   (n$=new filename, o$=old filename)
;==============================================================================
DS_NEW                  ;#24B7
    call GET2ARG_S      ;#2E6A  Get 2 strings from command line.
    call SYN_CHCK       ;#2E0E  Return if DOS is in syntax checking mode.
    call FIND_FTYPE     ;#24F1  Find type of the file ("B", "C", "D" or "#").
    call SEEKFILE       ;#2D49  Seek for file with same name of the second
                        ;       argument (old filename). Z flag is 1 if file
                        ;       is found; then, C=directory entry position.
    ld a,(CURRDRIVE)    ;       Define current drive as source.
    ld (SRCDRIVE),a
    jp nz,ER_NOFILE     ;#2358  Raise error condition if file with old name 
                        ;       does not exist.
    push bc             ;       Stack directory entry position.
    call GETENTRY       ;#27AE  Get file entry with old name and save in the
                        ;       FILENAME to FILETRACK system variables.
    call SEEKFILE       ;#2D49  Seek for the file with same name as the first 
                        ;       argument (new filename). ZERO=1 if file exists.
                        ;       New file name is copied into FILENAME.
    push af             ;       Save flags into stack.
    ld a,(SRCDRIVE)     ;       Compare previous drive ID with the current one.
    ld hl,CURRDRIVE     ;       Raise syntax error condition if they are not 
    cp (hl)             ;       equal, because both filenames must refer to the 
    jp nz,ER_SYNTX      ;#2DB3  same drive. 
    call ID_TYPE        ;#2384  Read disk configuration sector.
    pop af              ;       Restore flags from stack.
    jp z,ER_F_EXIST     ;#2CEB  Raise error condidtion if it was found a file 
                        ;       with same name of 1st argument (new filename).
    pop bc              ;       Unstack directory entry position.
;------------------------------------------------------------------------------
; DIR_RET (#24E6/9446)
; This part is common for DS_NEW, DS_MOVE and DS_SAVE. Update directory entry
;with data from FILENAME to FILETRACK DOS system variables.
;------------------------------------------------------------------------------
DIR_RET                 ;#24E6
    call PUTENTRY       ;#27BC  Get directory entry from DOS system variables
                        ;       FILENAME to FILETRACK and copy to printer 
                        ;       buffer.
    jp DIR_RET01        ;#216D  Jump backward to write directory entry.

;------------------------------------------------------------------------------
; Subroutine: CHecK LoaD/PeeK or PoKe
; Address: #24EC/9452
; Check (LDPKEXEC) and return result in the Z flag.
; Output: Z flag: 1=LOAD/0=PEEK or POKE.
;         A=(LDPKEXEC)
; Called by: LOADARG, FILELOAD01.
;------------------------------------------------------------------------------
CHK_LDPK                ;#24EC
    ld a,(LDPKEXEC)     ;       Fetch variable and check if it is 0.
    or a
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: FIND File TYPE
; Address: #24F1/9457
; Parse command line to find file type (BASIC, CODE, DATA or stream) and save
;code into FILETYPE system variable. 
; Input:  (CODEARG)=0 (get file type from command line);
;                  =1 or 3 (file type is "C").
; Output: (FILETYPE)=file type ("B", "C", "D" or "#");
;         B=file type
; Called by: DS_COPY, DS_ERASE, PK_ARG, LOADARG, DS_GOTO, DS_NEW.
;------------------------------------------------------------------------------
FIND_FTYPE              ;#24F1
    ld b,"C"            ;       Assign initially as "C" (CODE) type.
    ld a,(CODEARG)      ;       Jump to the end of subroutine if CODEARG DOS
    or a                ;       system variable was already been assigned as 1 
    jr nz,FIND_FTYPE01  ;#2510  or 3.
    call BAS_GETCHR     ;#2E26  Get character from command line.
    cp 175              ;       Assign B="C" if character was 'CODE' and finish 
    ld b,"C"            ;       subroutine.
    jr z,FIND_FTYPE01   ;#2510  
    cp 228              ;       Assign B="D" if character was 'DATA' and finish 
    ld b,"D"            ;       subroutine.
    jr z,FIND_FTYPE01   ;#2510 
    cp 35               ;       Assign B="#" if character was '#' and finish 
    ld b,"#"            ;       subroutine.
    jr z,FIND_FTYPE01   ;#2510 
    ld b,"B"            ;       No comparison matching, assign B="B".

FIND_FTYPE01            ;#2510
    ld hl,FILETYPE      ;       Store file type into DOS system variable.
    ld (hl),b    
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: READ KEY
; Address: #2515/9493
; Wait for a key press. Return code of the pressed key. 
; Output: A=code of key.
; Note: Registers B, C, D, E, H and L are preserved.
; Called by: RDWRSECT, OVERWRITE.
;------------------------------------------------------------------------------
READKEY                 ;#2515
    push hl             ;       Save HL, BC and DE values onto stack.
    push bc    
    push de    
    ld hl,WAITKEY       ;#3CA5  WAITKEY subroutine address, must be called by
    call CALLBAS        ;#2E36  CALLBAS because needs RST 56 subroutine of
                        ;       BASIC ROM.
    ld a,(LASTK)        ;       Fetch code of last pressed key.
    pop de              ;       Restore DE, BC and HL values from stack.
    pop bc    
    pop hl    
    and %11011111       ;       Reset bit to convert letters to upper case.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Routine: ERASE - Error No FiLe 
; Address: #2527/9511
; ERASE statement error handler. Raise 'File not found' error unless NOFILE 
;flag is nonzero. Even after finding and erasing a file, ERASEFILE subroutine 
;try again to erase file with same name (neccessary to erase all segments of a
;stream file); in that case, NOFILE flag is non zero.
;------------------------------------------------------------------------------
ERASE_ENFL              ;#2527
    ld a,(NOFILE)       ;       Raise 'File not found' error condition if 
    or a                ;       NOFILE flag is 0.
    jp z,ER_NOFILE      ;#2358 
    jp DSTM_RET         ;#2170  Otherwise, return to DOS interpreter.

;------------------------------------------------------------------------------
; Subroutine: OVERWRITE
; Address: #2531/9521
; Ask user if an existing file must be overwritten. 
; Input:  C=position of file entry in the directory (0-127).
; Output: Z flag=0 (key other than "Y" was pressed and file was not erased),
;               =1 ("Y" key was pressed and file was erased).
; Called by: COPYALL, DS_COPY.
;------------------------------------------------------------------------------
OVERWRITE               ;#2531
    push bc             ;       Save file entry position onto stack.
    ld a,#FF            ;       Flag: #FF=don't save disk configuration data 
    ld (SV_DCFG),a      ;       stored into printer buffer (see PRNCHR01).
    call BAS_CLS        ;#2E33  Clear screen.
    ld a,(CURRDRIVE)    ;       Get current drive ID number.
    add a,"A"           ;       Convert to drive letter (A-B).
    call PRNCHR01       ;#3D21  Print drive letter.
    ld a,58
    call PRNCHR01       ;#3D21  Print ":".
    ld hl,FILENAME      ;       HL=address of file name.
    call PR_FILENAM     ;#38FA  Print file name and type.
    ld hl,M_F_EXST      ;#37F3  Print "File exists", Enter, "Over write?",
                        ;       "(Y/N)".
    call PRNSTR01       ;#377B 
    call READKEY        ;#2515  Wait for a user key press.
    cp "Y"              ;       Check if key "Y" was pressed.
    push af             ;       Save Z flag onto stack.
    call BAS_CLS        ;#2E33  Clear screen.
    pop af              ;       Restore Z flag from stack.
    pop bc              ;       Restore file entry position from stack.
    ret nz              ;       Return if key other than "Y" was pressed.
    push bc             ;       Save file entry position onto stack.
    call BAS_CLS        ;#2E33  Clear screen.
    pop bc              ;       Restore file entry position from stack.
    call ERASENFILE     ;#2725  Erase file.
    xor a               ;       A=0 and Z flag=1.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: SEEK STReam File
; Address: #2569/9577
; Seek for stream type file ("#") in directory.
; Output: Z flag=1 (file found or file is not "#" type).
; Called by: COPYALL, DS_COPY. 
;------------------------------------------------------------------------------
SEEK_STRF               ;#2569
    ld a,(FILETYPE)     ;       Check if file type is "#" (stream).
    cp #23
    jr z,SEEK_STRF01    ;#2572  Jump if type is "#".
    xor a               ;       Return with Z flag=1 if not.
    ret    

SEEK_STRF01             ;#2572
    ld a,10             ;       Comparison of entry must match filename (8 
    ld (CMP_SIZE),a     ;       chars), file type (1 byte) and segment number 
                        ;       (1 byte).
    call SEEKFILE01     ;#2D4C  Seek for file in directory.
    ld a,09             ;       Restore normal value of DOS variable.
    ld (CMP_SIZE),a
    ret                 ;       End of subrotine.

;------------------------------------------------------------------------------
; Subroutine: COPY ALL
; Address: #2580/9600
; Copy all files of source drive to destination drive, except erased ones.
; Called by: DS_COPY.
;------------------------------------------------------------------------------
COPYALL                 ;#2580
    ld a,(FILENAME)     ;       Fetch first character of filename.
    cp "*"              ;       Jump to 'no file' error handler if this
    jp nz,ER_NOFILE     ;#2358  character is not "*".
    call BAS_STKFET     ;#2E4E  Fetch string data from stack.
    ex de,hl            ;       HL=start address of string.
    call GET_DRV        ;#2D1A  Check for presence of drive descriptor in the
                        ;       string (e.g. "A:").
    ld a,(hl)           ;       Fetch first character of filename.
    cp "*"              ;       Jump to syntax error handler if character is
    jp nz,ER_SYNTX      ;#2DB3  not "*" (DS_COPY already didn't find file).
    ld a,(CURRDRIVE)    ;       Assign drive of second argument as destination
    ld (DESTDRIVE),a    ;       drive.
    ld a,(DESTDRIVE)    ;       This line is superfluous.
    call SEL_DRIVE01    ;#3D74  Select destination drive.
    call ID_TYPE        ;#2384  Read disk configuration sector.
    ld a,#FF            ;       Initialize directory entry count as -1 (it will
    ld (SRC_ENTR) ,a    ;       incremented to 0).

COPYALL01               ;#25A9
    ld a,(SRCDRIVE)     ;       Select drive with source file.
    call SEL_DRIVE01    ;#3D74 
    call ID_TYPE        ;#2384  Read disk configuration sector.
    ld a,(SRC_ENTR)     ;       Increment directory entry position.
    inc a    
    ld (SRC_ENTR) ,a
    ld c,a              ;       Read directory entry info from disk.
    call GETENTRY       ;#27AE 
    ld a,(FILENAME)     ;       Finish (jump to DOS interpreter) if end of 
    cp 0                ;       directory mark (0) was found.
    jp z,DSTM_RET       ;#2170 
    cp 1                ;       Jump backward to skip an erased file if erased
    jr z,COPYALL01      ;#25A9  mark (1) was found.
    ld hl,FILEPARM1     ;       Copy source file entry data to a temporary 
    ld de,FILETEMP      ;       area.
    ld bc,7
    ldir
    ld a,(DESTDRIVE)    ;       Select destination drive.
    call SEL_DRIVE01    ;#3D74 
    call SEEKFILE01     ;#2D4C  Seek for the file in destination drive.
    jr nz,COPYALL02     ;#25E9  Jump forward if it is not found.
    call SEEK_STRF      ;#2569  Jump forward if file is not "#" (it is possible
    jr nz,COPYALL02     ;#25E9  to have more than one "#" file with same name
                        ;       in same disk).
    call OVERWRITE      ;#2531  Ask if existent file will be overwritten.
    jr nz,COPYALL01     ;#25A9  Jump backwards if not, skipping this file.

COPYALL02               ;#25E9
    call COPYFILE       ;#25F1  Copy file to destination drive.
    call WRT_BUFFER     ;#2EF0  Update directory entry sector of disk.
    jr COPYALL01        ;#25A9  Reenter loop to treat next file entry.

;------------------------------------------------------------------------------
; Subroutine: COPY FILE
; Address: #25F1/9713
; Copy a file.
; Called by: COPYALL, DS_COPY.
;------------------------------------------------------------------------------
COPYFILE                ;#25F1
    call READ_CS        ;#237F  Read configuration sector of destination disk.
    ld a,(BUFFER+CS_NFILE) ;    Jump to error handler if there is no space left
    cp 128              ;       in the directory (128 files), but ER_DIRFULL
    jp z,ER_NOSPACE     ;#2CE0  should be more appropriate message.
    ld hl,FILETEMP      ;       Copy directory entry data of source file to
    ld de,FILEPARM1     ;       FILEPARM1-FILETRACK DOS variables.
    ld bc,7
    ldir
    ld de,(FILESIZE)    ;       Fetch size of source file (number of sectors).
    ld d,0              ;       D=0, so DE is size of source file.
    or a                ;       C flag=0.
    ld hl,(BUFFER+CS_NFREE)
    sbc hl,de           ;       HL=(free sectors)-(size of file).
    jp c,ER_NOSPACE     ;#2CE0  Jump to error handler if HL is negative; 
    ld (BUFFER+CS_NFREE),hl ;   otherwise, store new number of free sectors.
    ld hl,(BUFFER+CS_FREES) ;   Former free track/sector ID will be start
    ld (FILESECT),hl    ;       track/sector ID of the copy of file.  
    push hl             ;       Stack track/sector ID.
    call COPYCHUNK      ;#26D3  Copy body of file.
    pop hl              ;       Unstack track/sector ID and store into DOS
    ld (FILESECT),hl    ;       system variables.
    ld hl,(RWSECID)     ;       Fetch track/sector ID after the last written 
    ld (BUFFER+CS_FREES),hl ;   sector and store as the first free track/sector
    ld hl,BUFFER+CS_NFILE   ;   ID.
    inc (hl)            ;       Increment number of files in the disk.
    ld c,(hl)           ;       Last file entry position is calculated 
    dec c               ;       subtracting one from number of files in disk.
    ld b,0              ;       BC=entry position.
    push bc             ;       Stack entry position.
    ld de,#0009         ;       Select D=track 0/E=sector 8 (see WRT_BUFFER). 
    ld (RWSECID),de
    call WRT_BUFFER     ;#2EF0  Save configuration sector to disk.
    pop bc              ;       Unstack entry position.
    call PUTENTRY       ;#27BC  Update directory.
    ret                 ;       End of routine.
  
;==============================================================================
; DOS Statement: COPY 
; Address: #2645/9797
; Copy file across different drives or duplicate file in the same disk but with
;differente name. Use of "*" wildcard allow copy of all files of source disk to
;another drive (in this case, at least one of source or destination drives must 
;be given in command line argument).
; Syntax: COPY <d$>,<s$>
;         COPY <d$>,<s$> CODE
;         COPY <d$>,<s$> DATA
;         COPY <d$>,<s$> #
;         COPY <a$>+"*",[b$]+"*"
;         COPY [a$]+"*",<b$>+"*"
; (s$=name of source file; d$=name of destination file; a$=destination drive,
;  b$=source drive)
;==============================================================================
DS_COPY                 ;#2645
    call GET2ARG_S      ;#2E6A  Get 2 strings from command line.
    call SYN_CHCK       ;#2E0E  Return if DOS is in syntax checking mode.
    call WKSPMEM        ;#27C0  Open temporary area in the workspace.
    call FIND_FTYPE     ;#24F1  Find type of source file.
    call SEEKFILE       ;#2D49  Seek for the source file in directory.
    ld a,(CURRDRIVE)    ;       Define current drive as the one with the source
    ld (SRCDRIVE),a     ;       file.
    jp nz,COPYALL       ;#2580  Jump to subroutine that copies all files if 
                        ;       source file was not found.
    call GETENTRY       ;#27AE  Get directory entry of source file.
    ld hl,FILEPARM1     ;       Copy source file directory entry data to 
    ld de,FILETEMP      ;       temporary place.
    ld bc,7
    ldir
    call SEEKFILE       ;#2D49  Seek for destination file in the directory.
    push af             ;       Stack Z flag and file entry position.
    push bc    
    ld a,(CURRDRIVE)    ;       Fetch destination drive ID (current drive) and 
    ld (DESTDRIVE),a    ;       store into DOS variable.
    ld a,(SRCDRIVE)
    call SEL_DRIVE01    ;#3D74  Select drive with source file
    call ID_TYPE        ;#2384  and get its configuration.
    ld a,(DESTDRIVE) 
    call SEL_DRIVE01    ;#3D74  Select destination drive and get its
    call ID_TYPE        ;#2384  configuration.
    pop bc              ;       Unstack Z flag and entry position.
    pop af
    jr nz,DS_COPY01     ;#2697  Jump forward if destination file not found.
    call SEEK_STRF      ;#2569  Jump forward if stream file with same name and
    jr nz,DS_COPY01     ;#2697  segment ID does not exist.
    call OVERWRITE      ;#2531  File exists, so ask user to erase it before
    jp nz,DSTM_RET      ;#2170  copying. Jump to DOS interpreter and exit file
                        ;       copy if answer is not "Y" (yes).
DS_COPY01               ;#2697
    call COPYFILE       ;#25F1  Copy the file.
    call WRT_BUFFER     ;#2EF0  Save directory entry.
    ld a,(FILETYPE)     ;       Finish statement execution if file is not 
    cp "#"              ;       stream type ("#") and return to DOS 
    jp nz,DSTM_RET      ;#2170  interpreter.
    ld a,10             ;       Use 10 bytes (filename, type and segment) for
    ld (CMP_SIZE),a     ;       file seek.
    ld hl,FILEPARM1     ;       Increment segment ID of stream file type.
    inc (hl)
    ld a,(SRCDRIVE)     ;       Select source drive.
    call SEL_DRIVE01    ;#3D74 
    call SEEK_STRF      ;#2569  Seek stream type file with same segment ID.
    jp nz,DSTM_RET      ;#2170  Finish copy if file not found.
    call GETENTRY       ;#27AE  Get file entry info.
    ld hl,FILEPARM1     ;       Copy entry info to a temporary area.
    ld de,FILETEMP
    ld bc,7
    ldir
    ld a,(DESTDRIVE)    ;       Select destination drive.
    call SEL_DRIVE01    ;#3D74 
    call ID_TYPE        ;#2384  Get configuration of drive.
    jr DS_COPY01        ;#2697  Copy stream file segment.

;------------------------------------------------------------------------------
; Subroutine: COPY CHUNK
; Address: #26D3/9939
; Input: (FILETEMP)=copy of entry info from FILEPARM1 to FILETRACK.
; Copy file body. Data are transferred in chunks of 4 KB or less, depending on 
;available RAM.
; Called by: COPYFILE.
;------------------------------------------------------------------------------
COPYCHUNK               ;#26D3
    ld a,(FILETEMP+4)   ;       Fetch number of remaining sectors to copy.
    or a    
    ret z               ;       Return if last sector was copied.
    push hl    
    ld hl,WSBUFFSIZ     ;       Check if remaining sectors fit into workspace 
    sub (hl)            ;       buffer calculating:
    pop hl              ;       A=(remaining sectors)-(buffer size).
    jr nc,COPYCHUNK02   ;#2719  Jump forward if they does not.
    ld a,(FILETEMP+4)   ;       Otherwise all sectors can be copied in one 
    ld b,a              ;       step, therefore counter is assigned with number 
    xor a               ;       of remaining sectors. Number of remaining 
    ld (FILETEMP+4),a   ;       sectors will be 0 for next pass, so reset it. 

COPYCHUNK01             ;#26E8
    push bc             ;       Stack number of sectors to copy.
    ld a,(SRCDRIVE)     ;       Select source drive.
    call SEL_DRIVE01    ;#3D74
    pop bc              ;       Unstack number of sectors to copy.
    push bc             ;       Stack number of sectors to copy.
    ld hl,(WKSPADD)     ;       Fetch workspace address.
    push hl             ;       Stack workspace address.
    ld de,(FILETEMP+5)  ;       D=track ID and E=sector ID of source file.
    call RDSECTORS      ;#2EEA  Read sectors from disk and write to workspace.
    ld hl,(RWSECID)     ;       Update track/sector ID (FILETEMP+5) with 
    ld (FILETEMP+5),hl  ;       next sector value
    ld a,(DESTDRIVE)    ;       Select destination drive.
    call SEL_DRIVE01    ;#3D74
    pop hl              ;       Unstack workspace address.
    pop bc              ;       Stack number of sectors to copy.
    ld de,(FILESECT)    ;       D=track/E=sector ID of destination drive.
    call WRSECTORS      ;#2EFA  Read data from workspace and write do disk.
    ld hl,(RWSECID)     ;       Update track/sector ID to be copied in the next 
    ld (FILESECT),hl    ;       pass (FILESECT) with values returned from 
    jr COPYCHUNK        ;#26D3  WRSECTORS (RWSECID/RWTRKID). Jump backward to 
                        ;       copy next chunk.

COPYCHUNK02             ;#2719
    ld (FILETEMP+4),a   ;       Remaining number of sectors for next pass.
    push hl    
    ld hl,WSBUFFSIZ     ;       Counter is set to the size of buffer (1-16 
    ld b,(hl)           ;       sectors).
    pop hl    
    xor a    
    jr COPYCHUNK01      ;#26E8  Jump to copy next chunk.

;------------------------------------------------------------------------------
; Subroutine: ERASE No FILE
; Address: #2725/10021
; Erase a file, but first mark NOFILE flag that it does not exist.
; Called by: OVERWRITE.
;------------------------------------------------------------------------------
ERASENFILE              ;#2725
    xor a               ;       A=0 and Z flag=1.
    ld (NOFILE),a       ;       Assign 0 to NOFILE flag.
    jr ERASEFILE        ;#2744  Jump to erase file.

;==============================================================================
; DOS Statement: ERASE 
; Address: #272B/10027
; Erase file, marking first byte of its directory entry. Erased file is not
;available anymore but its space in disk is not freed until MOVE statement is
;executed (unless for the last file of directory).
; Syntax: ERASE <n$>
;         ERASE <n$>CODE
;         ERASE <n$>DATA
;         ERASE <n$>#
; (n$=filename)
;==============================================================================
DS_ERASE                ;#272B
    call GET1ARG_S      ;#2E7C  Get filename from command line.
    call SYN_CHCK       ;#2E0E  Return if DOS is in syntax checking mode.
    call FIND_FTYPE     ;#24F1  Find type of file.
    xor a               ;       A=0.
    ld (NOFILE),a       ;       Initialize (NOFILE)=0 (file does not exist).
    call USTK_FILE      ;#38F1  Get filename from calculator stack and seek in
                        ;       the directory; Z flag=1 if file is found.
    call ERASEFILE      ;#2744  Erase file if it was found; 
    jp nz,ERASE_ENFL    ;#2527  otherwise, jump to error handler.
    jp DSTM_RET         ;#2170  Return to DOS interpreter.

;------------------------------------------------------------------------------
; Subroutine: ERASEFILE
; Address: #2744/10052
; Erase file. For the last file of directory, the first byte of filename is 
;replaced by 0 (end of directory), the total number of files (CS_FILE) are 
;decremented and occupied sectors are freed (CS_NFREE). For other files, the
;first byte of filename is replaced by 1 (erased file) and erased file counter 
;is incremented (CS_ERASF), but occupied sectors are not available until MOVE
;statement is executed.
; Input: C=number of entry in the directory (0-127);
;        Z flag=1 (file found).
; Called by: ERASENFILE, DS_ERASE.
;------------------------------------------------------------------------------
ERASEFILE               ;#2744
    ld a,(FILENAME)     ;       Save first character of filename in the DOS 
    ld (FSTCHAR),a      ;       system variable.
    ret nz              ;       Return if Z flag=0 (file not found).
    ld hl,NOFILE        ;       Change NOFILE flag to nonzero value (file 
    inc (hl)            ;       found).
    push bc             ;       Stack directory entry position.
    call READ_CS        ;#237F  Read configuration sector from disk.
    ld a,(BUFFER+CS_NFILE) ;    Fetch number of files in the disk.
    pop bc              ;       Unstack directory entry position.
    inc c               ;       Increment directory entry number and compare 
    cp c                ;       with number of files; jump forward if they are 
    jr nz,ERASEFILE01   ;#2760  different because it is not the last file.
    dec a               ;       Otherwise, decrement number of files in the 
    ld (BUFFER+CS_NFILE),a ;    disk.
    xor a               ;       Z flag=1 ('erasing last file of disk').

ERASEFILE01             ;#2760
    push af             ;       Stack 'erasing last file' flag.
    jr z,ERASEFILE02    ;#2767  Jump forward if erasing last file of disk;
    ld hl,BUFFER+CS_ERASF
    inc (hl)            ;       otherwise, increment number of erased files.

ERASEFILE02             ;#2767
    push bc             ;       Stack directory entry position.
    call WRT_BUFFER     ;#2EF0  Save configuration sector into disk.
    pop bc              ;       Unstack directory entry position.
    dec c               ;       Entry number of the file.   
    call GETENTRY       ;#27AE  Get directory entry of file.
    pop af              ;       Unstack 'erasing last file' flag.
    jp z,ERASEFILE03    ;#2776  Jump forward if erasing last file of disk and
    ld a,1              ;       keep A=0; otherwise, A=1.

ERASEFILE03             ;#2776
    ld (FILENAME),a     ;       Change first byte of filename to 1 (erased file 
                        ;       mark) or 0 (end of directory separator).
    push af             ;       Stack 'erasing last file' flag.
    call SV_ENTRY       ;#2EED  Save directory entry into disk.
    ld a,(FSTCHAR)      ;       Fetch saved first character of filename and 
    ld (FILENAME),a     ;       restore FILENAME to previous state.
    pop af              ;       Unstack 'erasing last file' flag.
    jr z,ERASEFILE04    ;#2778  Jump forward if last file was erased.
    call SEEKFILE01     ;#2D4C  Look for the file and execute subroutine again
    jr ERASEFILE        ;#2744  (neccessary for stream file splitted in 
                        ;       multiple segments).
ERASEFILE04             ;#2778
    call READ_CS        ;#237F  Read configuration sector from disk.
    ld hl,(FILESECT)        ;   Take start track/sector ID of file and copy as
    ld (BUFFER+CS_FREES),hl ;   new value for free space track/sector ID.
    ld de,(FILESIZE)        ;   E=FILESIZE and D=FILESECT
    ld hl,(BUFFER+CS_NFREE) ;   HL=number of free sectors of disk
    ld d,0                  ;   DE=FILESIZE because D=0.
    add hl,de               ;   Add number of sectors occupied by erased file 
    ld (BUFFER+CS_NFREE),hl ;   to calculate new value of free sectors.
    jp WRT_BUFFER       ;#2EF0  Save printer buffer to disk and return.

;------------------------------------------------------------------------------
; Subroutine: CHecK DELETed
; Address: #27A4/10148
; Check if a file is deleted.
; Input:  C=directory entry number of file (0-127).
; Output: Z flag=1 if deleted file;
;         A=first character of filename.
; Called by: DS_MOVE.
;------------------------------------------------------------------------------
CHKDELET                ;#27A4
    call GETENTRY       ;#27AE  Get directory entry of file.
    ld a,(FILENAME)     ;       Fetch first character of filename and compare 
    cp 1                ;       with 1 (deleted  mark). It returns Z flag=1 if 
    ret                 ;       this mark was found.

;------------------------------------------------------------------------------
; Unused code.
;------------------------------------------------------------------------------
    ld c,a
    
;------------------------------------------------------------------------------
; Subroutine: GET ENTRY
; Address: #27AE/10158
; Read directory from disk to printer buffer and copy an entry to DOS system 
;variables (FILENAME to FILETRACK).
; Input: C=directory entry number (0-127).
; Called by: DS_NEW, COPYALL, DS_COPY, DS_ERASE, ERASEFILE, CHKDELET, DS_MOVE, 
;LOADARG, SEEKSTRM, RD_STMFENT, DS_GOTO. 
;------------------------------------------------------------------------------
GETENTRY                ;#27AE
    xor a               ;       A=0, flag to copy from print buffer into DOS 
                        ;       system variables.
;------------------------------------------------------------------------------
; Common part for GETENTRY  and PUTENTRY .
;------------------------------------------------------------------------------
PUTENTRY01              ;#27AF
    push bc             ;       Stack directory entry number. 
    call CP_ENTRY       ;#2925  Copy directory entry.
    pop bc              ;       Unstack directory entry number.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Unused codes.
;------------------------------------------------------------------------------
    ld c,a    
    call PUTENTRY       ;#27BC 
    jp WRT_BUFFER       ;#2EF0 

;------------------------------------------------------------------------------
; Subroutine: PUTENTRY
; Address: #27BC/10172
; Read directory from disk to printer buffer and copy DOS sistem variables 
; (FILENAME to FILETRACK) to directory entry.
; Input: C=directory entry number (0-127).
; Called by: DS_NEW, COPYFILE, SV_ENTRY, SV_SGMT, WR_STMFENT.
;------------------------------------------------------------------------------
PUTENTRY                ;#27BC
    ld a,#FF            ;       A=#FF, flag to copy from DOS variable to 
                        ;       printer buffer.
    jr PUTENTRY01       ;#27AF  Jump backward to perform copy of entry.

;------------------------------------------------------------------------------
; Subroutine: WorK SPace MEMory
; Address: #27C0/10176
; Open a buffer into workspace. Depending on available RAM, a space with up to 
;4096 bytes (16 sectors) will be allocated.
; Output: (WKSPADD)=start address of buffer;
;         (WSBUFFSIZ)=size (number of sectors) of buffer.
; Called by: DS_COPY, DS_MOVE.
;------------------------------------------------------------------------------
WKSPMEM                 ;#27C0
    ld a,#FF            ;       Flag: #FF=do not clear workspace.
    ld (CLR_WSP),a
    call CHECKRAM       ;#27D1  Check available RAM.
    ld hl,(WORKSP)      ;       Assign workspace start address as start address 
    ld (WKSPADD),hl     ;       of newly opened area.
    jp BAS_BCSPC        ;#2EC2  Open BC bytes in the workspace and return.

;------------------------------------------------------------------------------
; Subroutine: CHECK RAM
; Address: #27D1/10193
; Check available free RAM. Any value greater than 4096 bytes (16 sectors) will  
;be truncated to that value. Used to allocate a buffer that can hold up to 16
;sectors.
; Output: A=number of sectors that fits in available RAM (1-16);
;         (WSBUFFSIZ)=number of sectors that fits in available RAM (1-16);
;         BC=number of bytes that fits in available RAM (256-4096).
; Called by: WKSPMEM.
;------------------------------------------------------------------------------
CHECKRAM                ;#27D1
    ld hl,#1F1A         ;       Address of FREE-MEM subroutine of BASIC ROM.
    call CALLBAS        ;#2E36  Call BASIC ROM routine.
    ld hl,65535         ;       Free RAM = 65535-BC.
    sbc hl,bc
    ld a,h              ;       Check amount of sectors that fits into 
    cp 16               ;       available RAM.
    jr nc,CHECKRAM01    ;#27E3  Jump if it is greater than or equal to 16;
    ld a,17             ;       otherwise, it will be 16 (17-1, owing to next
                        ;       'dec a' instruction).
CHECKRAM01              ;#27E3
    dec a               ;       Decrement number of available sectors and store 
    ld (WSBUFFSIZ),a    ;       in the DOS variable.
    ld b,a              ;       BC=256*(number of sectors).
    ld c,0
    ret                 ;       End of subroutine.
 
;------------------------------------------------------------------------------
; Subroutine: FREED SeCTors
; Address: #27EB/10219
; Sum number of sectors freed when one erased file is moved.
; Input:  HL=start track/sector ID of erased file.
; Output: (VAR_A)=start track/sector ID of erased file;
;         (VAR_C)=start track/sector ID of erased file;
;         (VAR_B)=number of sectors freed by move.
; Called by: DS_MOVE
;------------------------------------------------------------------------------
FREEDSCT                ;#27EB
    ld (VAR_A),hl       ;       Store start track/sector ID of erased file into
    ld (VAR_C),hl       ;       variables.
    ld de,(FILESIZE)    ;       Fetch size of erased file (number of sectors).
    ld hl,(VAR_B)       ;       Fetch number of sectors freed so far.
    ld d,0              ;       Reset D, so DE=size of erased file.
    add hl,de           ;       Add number of sectors of erased file to update
    ld (VAR_B),hl       ;       number of sector freed by move.
    ret                 ;       End of subroutine.

;==============================================================================
; DOS Statement: MOVE
; Address: #27FF/10239
; Move files, eliminating files marked as erased and freeing disk space.
; Syntax: MOVE
;==============================================================================
DS_MOVE                 ;#27FF
    call SYN_CHCK       ;#2E0E  Return if DOS is in syntax checking mode.
    call WKSPMEM        ;#27C0  Open temporary buffer in the workspace.
    call ID_TYPE        ;#2384  Read configuration sector of disk.
    ld a,(BUFFER+CS_ERASF)
    or a                ;       Check if there are erased files.
    jp z,DSTM_RET       ;#2170  Exit statement routine if none was found.

; Prepare to move files. This algorhitm resembles "bubble sort": directory is
;scanned many times and, when an erased file is found, it is replaced by the 
;next not erased file; the latter is then marked as erased file. This makes 
;erased files moving towards directory end ("sinking") and not erased file 
;towards directory start ("floating"). At the end, all erased files moved to
;bottom of directory are marked with the 'end of directory' code (0) and then 
;definetely eliminated.
    ld hl,0             ;       (VAR_B) is number of sectors freed by move;
    ld (VAR_B),hl       ;       initialized with 0 (no sector freed yet).
    ld c,#FF            ;       Initialize directory entry number with -1.

DS_MOVE01               ;#2817
; This loop scans directory until deleted file entry is found. The data of this
;file is stored in DOS variables: (ERASEDFL)=entry position, (ERASEDSC)=start
;track/sector ID.
    inc c               ;       Increment entry number to check next file.
    call CHKDELET       ;#27A4  Check if file is deleted. Jump backward if not,
    jr nz,DS_MOVE01     ;#2817  until deleted file is found.
    ld a,c    
    ld (ERASEDFL),a     ;       Store entry number of erased file.
    ld hl,(FILESECT)    ;       Store start track/sector ID of erased file.
    ld (ERASEDSC),hl
    call FREEDSCT       ;#27EB  Update number of freed sectors in (VAR_B).

DS_MOVE02               ;#282A
; After deleted file was found, do further directory scan to find a not deleted
;file entry.
    inc c               ;       Increment entry number to check next file.
    call CHKDELET       ;#27A4  Read entry and check if file is deleted. 
    jr z,DS_MOVE02      ;#282A  Jump backward if it is, until deleted file is 
                        ;       not found.
    cp 0                ;       Check if end of directory mark is found.
    jr nz,DS_MOVE04     ;#284C  Jump forward if it is not.

; No file entry without 'erased' mark was found until end of directory. 
;Directory is scanned once more, marking all deleted files with 'directory end'
;mark and releasing space occupied by them.
    ld a,(ERASEDFL)     ;       Fetch first erased file entry number.
    ld c,a    

DS_MOVE03               ;#2838
    inc c               ;       Increment entry number to check next file.
    call CHKDELET       ;#27A4  A=first character of filename.
    cp 0                ;       Jump forward and exit loop if end of directory 
    jr z,DS_MOVE05      ;#28A8  marker (0) is found.
    xor a               ;       Otherwise, mark this entry as end of directory
    ld (FILENAME),a     ;       and save new entry to disk.
    call SV_ENTRY       ;#2EED
    call FREEDSCT       ;#27EB  Update number of freed sectors in (VAR_B).
    jr DS_MOVE03        ;#2838  Jump backward to continue loop.

DS_MOVE04               ;#284C
; Move data of the file without erase mark to take the place of erased file.
; First, move the file body.
    ld a,(FILESIZE)     ;       Fetch number of sectors to move.
    ld (NSECMOV),a      ;       Number of sectors to move by MOVESECT.
    ld (NODISK),a       ;       Save size of file to move in another variable.
    ld hl,(FILESECT)    ;       Fetch start track/sector ID of file to move.
    ld (ERASEDSC),hl
    push bc             ;       Stack file entry position.
    call MOVESECT       ;#28E1  Move sectors of file body.
    pop bc              ;       Unstack file entry position.
; The moved file entry is marked as erased. 
    ld hl,(RWSECID)     ;       Fetch track/sector ID positioned after last 
    ld (ERASEDSC),hl    ;       written sector (next sector after file body).
    ld (FILESECT),hl    ;       Use these values to update file entry.
    xor a               ;       Set file size as 0 sector. This avoids moved
    ld (FILESIZE),a     ;       file space be counted by FREEDSCT.
    ld a,(FILENAME)     ;       Fetch first character of filename and save
    push af             ;       onto stack.
    ld a,1              ;       Mark file as erased.
    ld (FILENAME),a
    call SV_ENTRY       ;#2EED  Save entry to directory.
; The erased file entry is replaced with data of moved file entry.
    pop af              ;       Unstack character.
    ld (FILENAME),a     ;       Restore filename.
    ld a,(ERASEDFL)     ;       Fetch erased file entry position.
    ld c,a    
    ld hl,(VAR_C)       ;       Fetch start track/sector ID of erased file.
    ld (FILESECT),hl
    ld a,(NODISK)       ;       Fetch size of moved file.
    ld (FILESIZE),a
    call SV_ENTRY       ;#2EED  Save entry to the disk.

    ld a,(ERASEDFL)     ;       Fetch entry position after erased file, i.e.
    inc a               ;       moved file.
    ld c,a    
    call GETENTRY       ;#27AE  Get entry data.
    ld hl,(ERASEDSC)    ;       The new start track/sector ID is taken from
    ld (FILESECT),hl    ;       next sector after moved file body.
    call SV_ENTRY       ;#2EED  Save entry to the disk.
    ld a,(ERASEDFL)     ;       The moved file is now an erased file, thus it
    ld c,a              ;       must be treated by this routine.
    jp DS_MOVE01        ;#2817  Jump to the loop that looks for deleted file.

DS_MOVE05               ;#28A8
; Finish MOVE statement. Clear workspace and update disk configuration sector.
    ld hl,(WKSPADD)     ;       Start of workspace.
    ld bc,4096          ;       Delete 4096 bytes.
    call BAS_RECLM      ;#2ED7  Delete workspace.
    call READ_CS        ;#237F  Read configuration sector from disk.
    ld hl,(BUFFER+CS_NFREE) ;   Add former number of free sectors to number of
    ld de,(VAR_B)           ;   freed sectors and store the result (updated 
    add hl,de               ;   number of free sectors).
    ld (BUFFER+CS_NFREE),hl
    ld a,(BUFFER+CS_NFILE)  ;   Subtract number of erased files from number of 
    ld hl,BUFFER+CS_ERASF   ;   all disk files and store the result (updated 
    sub (hl)                ;   number of all disk files).
    ld (BUFFER+CS_NFILE),a
    ld (hl),0               ;   Reset number of erased sectors.
    ld hl,(ERASEDSC)        ;   The free space track/sector ID is updated with
    ld (BUFFER+CS_FREES),hl ;   ID of next sector after last moved file.
    push af             ;       Stack number of all disk files.
    call WRT_BUFFER     ;#2EF0  Write configuration sector to disk.
    pop af              ;       Unstack number of all disk files.
    ld c,a              ;       Get entry of first file after the last not 
    call GETENTRY       ;#27AE  erased file in the directory.
    xor a               ;       Put erased mark in the first character of
    ld (FILENAME),a     ;       directory entry.
    jp DIR_RET          ;#24E6  Jump backward to update directory entry.

;------------------------------------------------------------------------------
; Subroutine: MOVE SECTors
; Address: #28E1/10465
; Move file body to occupy place of an erased file. The sectors are read from 
;body of source file, stored in a buffer and written at body of erased file. 
; Input:  (VAR_A)=start track/sector ID of erased file;
;         (NSECMOV)=number of sectors to move;
;         (ERASEDSC)=start track/sector ID of file to move.
; Called by: DS_MOVE.
;------------------------------------------------------------------------------
MOVESECT                ;#28E1
    ld a,(NSECMOV)      ;       Fetch number of sectors to move.
    or a                ;       Return if there is no remaining sector.
    ret z    
    push hl             ;       Save HL.   
    ld hl,WSBUFFSIZ     ;       Check if remaining sectors fits in the buffer.
    sub (hl)
    pop hl              ;       Restore HL (useless
    jr nc,MOVESECT02    ;#2919  Jump forward if it doesn't.
    ld a,(NSECMOV)      ;       Otherwise, B=number of sectors to move, i.e.,
    ld b,a              ;       All remaining sectors will be moved.
    xor a               ;       Assign 0 to number of remaining sector. This 
    ld (NSECMOV),a      ;       will be the last sector moving.

MOVESECT01              ;#28F6
    push bc             ;       Stack number of sectors to move.
    ld hl,(WKSPADD)     ;       Fetch address of temporary workspace.
    push hl             ;       Stack workspace address.
    ld de,(ERASEDSC)    ;       DE=track/sector ID of file to be moved.
    call RDSECTORS      ;#2EEA  Read sectors to workspace.
    ld hl,(RWSECID)     ;       Update track/sector ID to next sector to be
    ld (ERASEDSC) ,hl   ;       read.
    pop hl              ;       Unstack workspace address.
    pop bc              ;       Unstack number of sectors to move.
    ld de,(VAR_A)       ;       DE=track/sector ID of deleted file space.
    call WRSECTORS      ;#2EFA  Write sectors to disk space of deleted file.
    ld hl,(RWSECID)     ;       Update track/sector ID to next sector to be
    ld (VAR_A),hl       ;       written.
    jr MOVESECT         ;#28E1  Jump to start of subroutine.

MOVESECT02              ;#2919
    ld (NSECMOV),a      ;       Update number of remaining sectors to move.
    push hl    
    ld hl,WSBUFFSIZ     ;       Number of sector to move is equal to number of
    ld b,(hl)           ;       256-byte blocks in the buffer.
    pop hl    
    xor a               ;       A=0. Perhaps a flag to RDSECTORS, but not
                        ;       really neccessary.
    jr MOVESECT01       ;#28F6  Jump backward to move sectors.

;------------------------------------------------------------------------------
; Subroutine: CoPy ENTRY
; Address: #2925/10533
; Copy directory entry between directory sector saved in the printer buffer and
;in the DOS sistem variables (FILENAME to FILETRACK). The direction of copy is
;determined by flag in A. The sector containing desired entry is read before
;executing copy.
; Input: C=entry position in the directory (0-127);
;        A=flag to indicate direction of copy,
;               0=copy from print buffer to DOS system variables,
;               NOT 0=copy from DOS variables to print buffer.
; Output: (RWSECID)=(read sector ID)+1;
;         (RWTRKID)=0.
; Called by: GETENTRY, PUTENTRY.
;------------------------------------------------------------------------------
CP_ENTRY                ;#2925
    push af             ;       Stack flag of copy direction.
    ld hl,TRK0SECT      ;       Initialize sector number to be read from 
    ld (hl),0           ;       track 0 and sector 0.

; Next loop will evaluate sector number where entry C is saved.
;   (sector number)=INT(C/16)
;   (entry number in the buffer)=C%16
    ld a,c    
CP_ENTRY01              ;#292C
    sub 16              ;       Each sector can hold 16 entries, therefore 
    jr c,CP_ENTRY02     ;#2933  subtract 16 from sector number and, if result 
                        ;       is negative, jump forward;
    inc (hl)            ;       otherwise, increase sector number and continue 
    jr CP_ENTRY01       ;#292C  in the loop.

CP_ENTRY02              ;#2933
    add a,16            ;       Recover entry position to the last value before
    ld c,a              ;       subtraction.
    push bc             ;       Stack entry number.
    call READT0SX       ;#2364  Read sector into printer buffer.
    pop bc              ;       Unstack entry number.
    pop af              ;       Unstack flag of copy direction.
    call DIRENTRYPOS    ;#2D3D  HL=address of entry in the print buffer.
    ld de,FILENAME      ;       DE=address of DOS system variables.
    ld bc,16            ;       BC=16 bytes to be copied.
    or a                ;       Check value of A; if A=0, jump forward to copy 
    jr z,CP_ENTRY03     ;#2949  from print buffer to DOS variables; otherwise,
    ex de,hl            ;       copy from DOS variables to printer buffer.

CP_ENTRY03              ;#2949
    ldir                ;       Copy data.
    ret                 ;       End of subroutine.

;==============================================================================
; DOS Statement: LOAD 
; Address: #294C/10572
; Load a BASIC program, sequence of bytes or array from disk.
; Syntax: LOAD <n$>
;         LOAD <n$> CODE [addr][,<len>]
;         LOAD <n$> DATA <v()/v$()> [,<w()/w$()>] ...
;   (n$=filename; addr=start address; len=length; v()=numeric array; v$()=
;    character array; w()=numeric array; w$()=character array)
;==============================================================================
DS_LOAD                 ;#294C
    call RS_LDEXEC      ;#2981  Set flag to LOAD/SAVE type statement.

;------------------------------------------------------------------------------
; PEEKPOKE01 (#294F/10575)
; Common part for DS_LOAD, DS_PEEK and DS_POKE.
;------------------------------------------------------------------------------
PEEKPOKE01              ;#294F
    call FILELOAD       ;#2965  Parse command line arguments and, when in 
                        ;       execution mode, load file from disk.
    call SYN_CHCK       ;#2E0E  Return if DOS is in syntax checking mode.
    ld a,#FF            ;       Set variable to 'PEEK statement in execution'.
    ld (LDPKEXEC),a
    ld a,(FILETYPE)     ;       Check file type. For BASIC file, jump to the 
    cp "B"              ;       routine that executes an autostarting program 
    jp z,EXEC_BAS       ;#20F1  or give back control to the BASIC editor.
    jp DSTM_RET         ;#2170  For other types, return to DOS interpreter.

;------------------------------------------------------------------------------
; Subroutine: FILE LOAD
; Address: #2965/10597
; Parse command line arguments and load file from disk.
; Called by: DS_LOAD, DS_RUN.
;------------------------------------------------------------------------------
FILELOAD                ;#2965
    call LOADARG        ;#29A9  Fetch arguments from command line.
    call SYN_CHCK       ;#2E0E  Return if DOS is in syntax checking mode.
    call LOADPARM       ;#29DD  Parse parameters.
    jp FILELOAD01       ;#2A4D  Jump forward to read from/write to disk.

;------------------------------------------------------------------------------
; Subroutine: LoadD CoDe ARGuments
; Address: #2971/10609
; Return if no argument was found after 'CODE' keyword, otherwise fetch up to 2
;numeric arguments.
; Output: (VAR_B)=first argument (start address) if any;
;         (VAR_C)=second argument (length) if any, or first argument;
;         (CODEARG)=1 if one argument was found;
;                  =3 if second argument was found.
; Called by: LOADARG.
;------------------------------------------------------------------------------
LDCD_ARG                ;#2971
    ld hl,(CH_ADD)      ;       Make HL pointing for command line.
    inc hl              ;       Advance one position and fetch character.
    ld a,(hl)
    cp 13               ;       Return if character is 'Enter'.
    ret z    
    ld a,1              ;       At least one argument was found.
    ld (CODEARG),a
    call PARAM_C01      ;#2E88  Fetch parameters for CODE. 
                        ;       Exit by RS_LDEXEC subroutine.

;------------------------------------------------------------------------------
; Subroutine: ReSet LoaD EXECution
; Address: #2981/10625
; Reset LDPKEXEC DOS system variable, signaling statement is LOAD/SAVE type
;instead PEEK/POKE.
; Called by: LDCD_ARG, DS_MERGE, DS_SAVE, DS_RUN, DS_LOAD.
;------------------------------------------------------------------------------
RS_LDEXEC               ;#2981
    xor a               ;       A=0.
    ld (LDPKEXEC),a     ;       Reset DOS system variable.
    ret                 ;       End of Subroutine.

;------------------------------------------------------------------------------
; Subroutine: PeeK (PoKe) ARGuments
; Address: #2986/10630
; Parse command line and get arguments for PEEK or POKE statement.
; Output: (VAR_A)=start address of file data;
;         (VAR_C)=sector offset;
;         (VAR_B)=sector offset;
;         (CODEARG)=0.
; Called by: LOADARG.
;------------------------------------------------------------------------------
PK_ARG                  ;#2986
    call FIND_FTYPE     ;#24F1  Fetch type of file.
    ld a,"B"
    cp b    
    jr nz,PK_ARG01      ;#2995  Jump forward if type is not "B" (BASIC).
    ld hl,(CH_ADD)      ;       Otherwise, move back interpreter cursor one
    dec hl              ;       position.
    ld (CH_ADD),hl

PK_ARG01                ;#2995
    call PARAM_C01      ;#2E88  Get numeric arguments.
    ld hl,(VAR_B)       ;       Store start address into (VAR_A).
    ld (VAR_A),hl
    ld hl,(VAR_C)       ;       Store sector offset into (VAR_B).
    ld (VAR_B),hl
    xor a               ;       Flag=0.
    ld (CODEARG),a
    ret                 ;       End of subroutine.
  
;------------------------------------------------------------------------------
; Subroutine: LOAD ARGuments
; Address: #29A9/10665
; Fetch arguments for LOAD, PEEK, POKE, RUN and MERGE statements.
; Called by: FILELOAD, DS_MERGE.
;------------------------------------------------------------------------------
LOADARG                 ;#29A9
    call NOARG          ;#23AA  Look for argument. Execute 'RUN "boot"' if none
    jp z,RUNBOOT        ;#220D  was found.
    call GET1ARG_S      ;#2E7C  Fetch filename from command line. 
    call CHK_LDPK       ;#24EC  Check (LDPKEXEC) flag and, if nonzero, get
    call nz,PK_ARG      ;#2986  arguments for PEEK/POKE statement.
    call BAS_GETCHR     ;#2E26  Fetch next character from line. 
    cp 175              ;       Get arguments for LOAD CODE if character is 
    call z,LDCD_ARG     ;#2971  'CODE'.
    cp 228              ;       Check if character is 'DATA'.
    push af             ;       Stack Z flag (1='DATA').
    call CHK_LDPK       ;#24EC  Fetch type of file if statement in execution is 
    call z,FIND_FTYPE   ;#24F1  'LOAD'.
    pop af              ;       Unstack Z flag (1='DATA').
    call z,FETARRAY     ;#2CAB  Fetch array info if 'DATA'.
    call SYN_CHCK       ;#2E0E  Return if DOS is in syntax checking mode.
    call USTK_FILE      ;#38F1  Seek file in the directory.
    jp nz,ER_NOFILE     ;#2358  Raise error condition if file was not found.
    call GETENTRY       ;#27AE  Get directory entry of the file.
    call LOADBUFF       ;#3F96  Restore printer buffer area.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: LOAD PARaMeters
; Address: #29DD/10717
; Parse parameters for LOAD and another statements.
; Input:  (CODEARG)=0, 1 or 3 (see DOS system variables).
; Output: HL=start address;
;         D=start track ID, E=start sector ID;
;         A=size (number of sectors) of file;
;         (VAR_C)=data length;
;         (CODEARG)=3 (if last sector will be truncated).
; Called by: FILELOAD.
;------------------------------------------------------------------------------
LOADPARM                ;#29DD
; Select parameters from command line arguments or directory entry data.
    ld a,(CODEARG)      ;       (CODEARG) is 1 or 3 when start address was 
    or a                ;       given in the command line argument. Thus, start 
    ld hl,(FILEPARM1)   ;       address (HL) is taken from the file entry 
    jr z,LOADPARM01     ;#29E9  unless (CODEARG) is not 0; in the later, start
    ld hl,(VAR_B)       ;       address is taken from command line argument.

LOADPARM01              ;#29E9
    ld de,(FILESECT)    ;       Fetch start track/sector ID of file.
    cp 3                ;       Check if (CODEARG) is 3.
    ld a,(FILESIZE)     ;       Get file size (number of sectors) from entry.
    push de             ;       Stack start track/sector ID.
    ld de,(FILEPARM2)   ;       Get data length from directory entry, but if
    jr nz,LOADPARM02    ;#29FD  (CODEARG) is 3, get parameter from the second
    ld de,(VAR_C)       ;       argument of command line.

LOADPARM02              ;#29FD
    ld b,a              ;       Save file size temporarily into B register.
    ld (VAR_C),de       ;       Store data lenght into VAR_C variable.
    ld a,(FILETYPE)     ;       Check if file type is "C" (CODE).
    cp "C"
    ld a,b              ;       Restore file size (number of sectors).
    jr nz,LOADPARM05    ;#2A31  Jump forward if type is not CODE.
    ld a,b              ;       Restore file size (number of sectors).
    cp d                ;       Jump forward if (number of sector)=MSB of data
    jr z,LOADPARM03     ;#2A28  length.
    dec a    
    cp d                ;       Jump forward if (number of sector)-1=MSB of 
    ld a,b              ;       data length.
    jr z,LOADPARM03     ;#2A28
    ld a,(CODEARG)      ;       Jump forward if flag is 3 (second argument of
    cp 3                ;       LOAD <n$>CODE was found).
    ld a,b    
    jr z,LOADPARM03     ;#2A28
    xor a               ;       Otherwise, reset (CODEARG) to load all bytes of
    ld (CODEARG),a      ;       the last sector.
    ld d,b              ;       Length is 256*B (B=number of sectors).
    ld e,0
    ld (VAR_C),de       ;       Store length into VAR_C variable.
    jr LOADPARM04       ;#2A2D

LOADPARM03              ;#2A28
    ld a,3              ;       (CODEARG)=3: load only neccessary number of 
    ld (CODEARG),a      ;       bytes of last sector.

LOADPARM04              ;#2A2D
    ld a,b              ;       Fetch file size (number of sectors).
    call TRUNCLEN       ;#2F59  Truncate file length if necessary.

LOADPARM05              ;#2A31
    push af             ;       Stack file size.
    ld a,h              ;       Jump forward if address is not within printer 
    cp #5B              ;       buffer (#5B00-#5BFF).
    jr nz,LOADPARM06    ;#2A3B
    xor a               ;       (CODEARG)=0: load all 256 bytes of the last 
    ld (CODEARG),a      ;       sector.

LOADPARM06              ;#2A3B
    ld a,(FILETYPE)     ;       Fetch file type.
    cp "B"
    push af             ;       Stack file type.
    call z,MKBASROOM    ;#2AD3  Make space for BASIC program if type "B".
    pop af              ;       Unstack file type.
    cp "D"
    call z,MKARRROOM    ;#2B03  Make space for array if type "D".
    pop af              ;       Unstack file size.
    pop de              ;       Unstack start track/sector ID.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Routine: FILELOAD01
; Address: #2A4D/10829.
; Final part of FILELOAD subroutine, read from disk for LOAD/PEEK or write for
;POKE.
; Called by: FILELOAD, DS_MERGE.
;------------------------------------------------------------------------------
FILELOAD01              ;#2A4D
    ld b,a              ;       B=file size.
    call CHK_LDPK       ;#24EC  Jump forward if LOAD statement (Z flag=1).
    jr z,FILELOAD02     ;#2A5A
    push af             ;       Save (LDPKEXEC) flag onto stack.
    call SCT_OFF        ;#2B3E  Find sector in the disk for PEEK/POKE 
                        ;       statement.
    pop af              ;       Recover (LDPKEXEC) flag from stack.
    cp #FF              ;       Check if statement is PEEK (flag=#FF) or POKE.

FILELOAD02              ;#2A5A
    push af             ;       Save Z flag onto stack.
    call z,RDSECTORS    ;#2EEA  Read disk sector for LOAD or PEEK.
    pop af              ;       Recover Z flag from stack.
    jr z,FILELOAD03     ;#2A64  Jump forward if statement is LOAD/PEEK, 
    jp WRSECTORS        ;#2EFA  otherwise write disk sector (POKE) and return.

FILELOAD03              ;#2A64
    ld a,(CODEARG)      ;       Read the last sector and write to RAM only the  
    cp 3                ;       real data if (CODEARG) is 3.
    call z,LASTSECTOR   ;#3FAE
    ld hl,(E_LINE)      ;       Put end separator (#80) in the last byte of 
    dec hl              ;       BASIC program/variable area.
    ld (hl),#80
    ret                 ;       End of subroutine.

;==============================================================================
; DOS Statement: PEEK 
; Address: #2A73/10867
; Read one sector of a file and write to RAM.
; Syntax: PEEK <n$> <addr>,<offset>
;         PEEK <n$> CODE <addr>,<offset>
;         PEEK <n$> DATA <addr>,<offset>
;         PEEK <n$> # <addr>,<offset>
; (n$=filename; addr=address where sector will be written to; offset= sector
;  offset number in the file)
;==============================================================================
DS_PEEK                 ;#2A73
    ld a,#FF            ;       Flag to signal 'execute PEEK statement'.
    jr PEEKPOKE         ;#2A79  Jump forward.

;==============================================================================
; DOS Statement: POKE
; Address: #2A77/10871
; Write 256 bytes of RAM into sector of a file.
; Syntax: POKE <n$> <addr>,<offset>
;         POKE <n$> CODE <addr>,<offset>
;         POKE <n$> DATA <addr>,<offset>
;         POKE <n$> # <addr>,<offset>
; (n$=filename; address=address with data to write to sector; offset=sector 
;  offset number in the file)
;==============================================================================
DS_POKE                 ;#2A77
    ld a,#EE            ;       Flag to signal 'POKE statement in execution'.

;------------------------------------------------------------------------------
; PEEKPOKE (#2A79/10873)
; Common part for DS_PEEK and DS_POKE.
;------------------------------------------------------------------------------
PEEKPOKE                ;#2A79
    ld (LDPKEXEC),a     ;       Store flag into DOS system variable.
    jp PEEKPOKE01       ;#294F  Jump backward.

;==============================================================================
; DOS Statement: MERGE 
; Address: #2A7F/10879
; Merge BASIC program loaded from disk with the program already stored in RAM.
; Syntax: MERGE <n$>
;   (n$=filename)
;==============================================================================
DS_MERGE                ;#2A7F
    ld a,#FF            ;       Floating point constants must be deleted from
    ld (RM_FPC),a       ;       line.
    call LOADARG        ;#29A9  Fetch arguments from line.
    call SYN_CHCK       ;#2E0E  Return if DOS is in syntax checking mode.
    ld a,(FILETYPE)     ;       Check type of file.
    cp "B"              ;       Raise syntax error condition if "B" type  
    jp nz,ER_SYNTX      ;#2DB3  (BASIC) file is not found.
    ld bc,(FILEPARM1)   ;       BC=BASIC program and variables length.
    push bc             ;       Stack BASIC and variables length.
    inc bc              ;       One more byte to store final separator byte.
    ld hl,#0030         ;       Call BC-SPACES subroutine (#0030/48) of BASIC 
    call CALLBAS        ;#2E36  ROM to create new space in the workspace.
    ld (hl),#80         ;       Put separator byte at the end of created space.
    ex de,hl            ;       HL=start address of new space.
    pop de              ;       Unstack BASIC and variables length
    push hl             ;       Stack workspace address.
    ld de,(FILESECT)    ;       D=start track ID, E=start sector ID.
    ld a,(FILESIZE)     ;       A=size (number of sectors) of file.
    ld b,a              ;       Save A in B.
    call RS_LDEXEC      ;#2981  Set flag to LOAD/SAVE type statement.
    ld a,b              ;       Restore A from B.
    call FILELOAD01     ;#2A4D  Load BASIC into workspace.
    pop hl              ;       Unstack workspace address.
    rst 32              ;       Save content of HL.  
    ld de,(PROG)        ;       Fetch BASIC program start address.
    ld hl,#08D2         ;       Call ME-NEW-LP subroutine of BASIC ROM. This 
    call CALLBASHL      ;#2ECF  routine merges lines of two BASIC programs.
    jp DSTM_RET         ;#2170  Return to DOS interpreter.

;------------------------------------------------------------------------------
; Subroutine: TEST SPACE
; Address: #2AC1/10945
; Test availability of enough　RAM to load new BASIC program or array. BASIC
;error condition is raised if there is not enough memory.
; Input:  HL=size of already occupied space;
;         DE=length of file to load.
; Called by: MKBASROOM, MKARRROOM.
;------------------------------------------------------------------------------
TESTSPACE               ;#2AC1
    ex de,hl            ;       Compare length of file to load with size of
    scf                 ;       already occupied space plus 1; return if  
    sbc hl,de           ;       difference is negative (there is enough space
    ret c               ;       to load file data).
    ld de,10            ;       Add 10 more bytes onto necessary memory.
    add hl,de    
    ld b,h              ;       Test availability of BC bytes of RAM with 
    ld c,l              ;       TESTROOM (#1F05/7941) BASIC ROM routine. Flag
    ld hl,#1F05         ;       C=1 if there are enough RAM.
    call CALLBAS        ;#2E36  Call BASIC ROM routine.
    ret                 ;       End of subroutine.
  
;------------------------------------------------------------------------------
; Subroutine: MaKe BASic ROOM
; Address: #2AD3/10963
; Check existence of enough space of RAM, erase old program and make room to
;load new BASIC program.
; Input:  (FILEPARM1)=total length of file (BASIC program plus variables);
;         (FILEPARM2)=length of BASIC.
; Output: HL=start address of BASIC program=(PROG).
; Called by: LOADPARM.
;------------------------------------------------------------------------------
MKBASROOM               ;#2AD3
    ld de,(PROG)        ;       DE=start address of BASIC program.
    ld hl,(E_LINE)      ;       HL=end address of BASIC variable area.
    dec hl
    push hl             ;       Stack addresses.
    push de
    sbc hl,de           ;       HL=length of BASIC program with variables.
    ld de,(FILEPARM1)   ;       DE=total length of file.
    push de             ;       Stack total length.
    call TESTSPACE      ;#2AC1  Test availability of RAM.
    pop bc              ;       Unstack total length.
    pop de              ;       Unstack addresses.
    pop hl
    push bc             ;       Stack total length.
    rst 32              ;       Save end address of BASIC area, i.e. HL.
    ld hl,#19E5         ;       Call RECLAIM-1 routine of BASIC ROM to erase 
    call CALLBASHL      ;#2ECF  BASIC program and variables.
    pop bc              ;       Restore total length of BASIC from stack.
    call BAS_MKROOM     ;#2EDD  Make space in RAM.
    inc hl              ;       HL=start address of new space.
    ld bc,(FILEPARM2)   ;       BC=length of BASIC program without variables.
    add hl,bc           ;       Calculate address of BASIC variable area and 
    ld (VARS),hl        ;       store into system variable.
    ld hl,(PROG)        ;       HL=start of BASIC program area.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine:MaKe ARRay ROOM
; Address: #2B03/11011
; Check existence of enough space of RAM, erase old array and make room to load
;load new array.
; Input:  (FILEPARM2)=length of array to load;
;         (VAR_B)=length of array already existent in RAM;
;         (VARNAME)=1 character ID of array.
; Output: HL=start address of array to load.
; Called by: LOADPARM.
;------------------------------------------------------------------------------
MKARRROOM               ;#2B03
    ld de,(FILEPARM2)   ;       Length of array taken from directory entry.
    ld hl,(VAR_B)       ;       Lenght of array present in variable area.
    push hl             ;       Save length onto stack.
    call TESTSPACE      ;#2AC1  Test availability of space in memory.
    pop hl              ;       Restore length from stack.
    ld a,h              ;       Jump forward if array of same name does not 
    or l                ;       exist in memory (i.e., (VAR_B)>0); otherwise, 
    jr z,MKARRROOM01    ;#2B23  existing array will be deleted from RAM.
    ld hl,(VAR_A)       ;       Fetch start address and go back 3 bytes to 
    dec hl              ;       include ID letter of variable and 2 bytes of 
    dec hl              ;       length field.
    dec hl
    ld bc,(VAR_B)       ;       Fetch length of array data and add 3 bytes 
    inc bc              ;       (see above comment).
    inc bc    
    inc bc    
    call BAS_RECLM      ;#2ED7  Delete array from memory.

MKARRROOM01             ;#2B23
    ld hl,(E_LINE)      ;       HL=end address of variable area.
    dec hl
    ld bc,(FILEPARM2)   ;       BC=length of array.
    push bc             ;       Stack length.
    inc bc              ;       Increment length to store variable ID and 2 
    inc bc              ;       bytes for data length.
    inc bc    
    call BAS_MKROOM     ;#2EDD  Make room to load array.
    inc hl              ;       Place pointer at start of new room.
    ld a,(VARNAME)      ;       Fetch variable ID and put into that byte.
    ld (hl),a    
    inc hl              ;       Increment pointer.
    pop de              ;       Unstack length and put the LSB into second byte
    ld (hl),e           ;       of new room.
    inc hl              ;       Increment pointer again and put MSB of length 
    ld (hl),d           ;       into third byte.
    inc hl              ;       Increment pointer. Array data will be loaded
                        ;       from that address.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: SeCTor OFFset
; Address: #2B3E/11070
; Select one sector of a file  
; Input:  B=file size (number of sectors);
;         D=track/E=sector ID of first sector of file;
;         (VAR_A)=start address;
;         (VAR_B_L)=sector offset.
; Output: HL=start address;
;         D=track/E=sector ID of sector at offset position;
;         B=1 (1 sector do write/read).
; Called by: FILELOAD01.
;------------------------------------------------------------------------------
SCT_OFF                 ;#2B3E
    ld a,(VAR_B_L)      ;       Fetch sector offset.
    ld c,b              ;       C=file size (number of sectors).
    ld b,a              ;       B=sector offset.
    ld a,c              ;       A=file size.
    cp b                ;       Check if file size is equal to or greater than 
    jr c,ER_OVERFL      ;#2B60  sector offset; raise overflow error if not.
    ld a,b    
    or a                ;       Check if offset value is 0; raise syntax error
    jp z,ER_SYNTX       ;#2DB3  if it is.
    dec b               ;       Decrement offset.
    jr z,SCT_OFF03      ;#2B5A  Jump forward if offset=1 (first sector).
    ld a,16             ;       Max sector ID (15) plus 1.

SCT_OFF01               ;#2B51
    inc e               ;       Increment sector ID number.   
    cp e                ;       Jump forward if it not exceeded upper limit 
    jr nz,SCT_OFF02     ;#2B58  (i.e. E<16).
    ld e,0              ;       Otherwise, select first sector of the next 
    inc d               ;       track.

SCT_OFF02               ;#2B58
    djnz SCT_OFF01      ;#2B51  Repeat until desired sector is reached.

SCT_OFF03               ;#2B5A
    ld b,1              ;       B=1 sector to be transferred.
    ld hl,(VAR_A)       ;       HL=start address.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Error routine: ER_OVERFL
; Address: #2B60/11104
; Record number overflow, a out of range file sector was requested.
; Called by: SCT_OFF.
;------------------------------------------------------------------------------
ER_OVERFL               ;#2B60
    ld hl,M_RECOF       ;#3992  Message: "Rec.  O/F".
    ld a,5              ;       DOS error code 5.
    jp DSTM_ERRET       ;#2CE5  Jump to DOS error handler.

;------------------------------------------------------------------------------
; Subroutine: FILe EXISTs
; Address: #2B68/11112
; Check if file already exists and if directory is full. When either of 
;status is found, apropriate error hendler is called.
; Called by: DS_SAVE.
;------------------------------------------------------------------------------
FILEXIST                ;#2B68
    call USTK_FILE      ;#38F1  Take filaname from stack and seek in the
    jp z,ER_F_EXIST     ;#2CEB  directory. Raise error if file exists.

;------------------------------------------------------------------------------
; Subroutine: DIRectory FULL
; Address: #2B6E/11118
; Check if limit of 128 entries in the directory was exceeded.
; Called by: SV_SGMT. 
;------------------------------------------------------------------------------
DIRFULL                 ;#2B6E
    call READ_CS        ;#237F  Read configuration sector.
    ld a,(BUFFER+CS_NFILE)
    cp 128              ;       Jump to directory full error handler if there
    jp z,ER_DIRFULL     ;#3797  are already 128 files in directory.
    ret                 ;       Otherwise, return.
 
;==============================================================================
; DOS Statement: SAVE 
; Address: #2B7A/11130
; Save to disk a BASIC program, an arbitrary block of bytes (CODE), a numeric 
;or character array (DATA) or a dump of the video RAM (SCREEN$).
;All data types of BASIC tape routines are supported by DOS.
; Syntax: SAVE <n$> [LINE <line>]
;         SAVE <n$> CODE <addr>,<len>
;         SAVE <n$> DATA <a()>
;         SAVE <n$> DATA <a$()>
;         SAVE <n$> SCREEN$
; (n$=filename; line=BASIC line number to be executed after program loading;
;  addr=start address of block to be saved; len=number of bytes to save;
;  a()=numeric array; a$()=character array)
;==============================================================================
DS_SAVE                 ;#2B7A
    call RS_LDEXEC      ;#2981  Set flag to LOAD/SAVE type statement.
    ld hl,0             ;       Initialize auto execution line of BASIC program 
    ld (NODISK),hl      ;       with 0. 
    call GET1ARG_S      ;#2E7C  Get string (filename) from command line.
    call BAS_GETCHR     ;#2E26  Get next character code from command line.
    cp 175              ;       Jump forward if code is 'CODE'.
    jr z,DS_SAVE05      ;#2BE3
    cp #CA              ;       Jump forward if code is not 'LINE'.
    jr nz,DS_SAVE01     ;#2BA2
    call GETARG_I       ;#2EA8  Evaluate argument and put in (VAR_C).
    call SYN_CHCK       ;#2E0E  Return if DOS is in syntax checking mode.
    ld hl,(VAR_C)       ;       Get numeric argument of LINE and put into 
    ld (NODISK),hl      ;       (NODISK).
    ld hl,FILETYPE      ;       Set HL as pointer to FILETYPE.
    jr DS_SAVE03        ;#2BC9  Jump forward.

DS_SAVE01               ;#2BA2
    cp 170              ;       Jump forward if code is not 'SCREEN$'.
    jr nz,DS_SAVE02     ;#2BB7
    ld hl,VID_RAM       ;       Parameter 1 is video RAM address.
    ld (VAR_A),hl
    ld hl,6912          ;       Lenght of file and parameter 2 is 6912 bytes.
    ld (VAR_B),hl
    ld (VAR_C),hl
    jr DS_SAVE06        ;#2BF2  Jump forward to save as CODE file.

DS_SAVE02               ;#2BB7
    call SYN_CHCK       ;#2E0E  Return if DOS is in syntax checking mode.
    call BAS_GETCHR     ;#2E26  Get code of next character of line editor.
    ld hl,FILETYPE      ;       Set HL as pointer to FILETYPE.
    cp 228              ;       Jump forward if code is 'DATA'.
    jr z,DS_SAVE04      ;#2BD6
    cp 13               ;       Jump to syntax error handler if code is not 13, 
    jp nz,ER_SYNTX      ;#2DB3  i.e., is not an end of line (it should be 
                        ;       'SAVE <n$>' statement here).
DS_SAVE03               ;#2BC9
; Save BASIC program.
    ld (hl),"B"         ;       Assign BASIC type file to (FILETYPE).
    call FILEXIST       ;#2B68  Check if file already exists and there is
                        ;       space in the directory.
    call BAS_RMFP       ;#2EB9  Remove floating point code from command line.
    call PARAM_B        ;#2C8D  Fetch parameters to save BASIC type file.
    jr DS_SAVE07        ;#2BFD  Jump forward.

DS_SAVE04               ;#2BD6
; Save DATA type array.
    ld (hl),"D"         ;       Assign DATA type file to (FILETYPE).
    call FILEXIST       ;#2B68  Check if file already exists and there is space
                        ;       in the directory.
    call PARAM_D        ;#2CB6  Look for the variable and evaluate it.
    jr nc,DS_SAVE07     ;#2BFD  Jump forward if variable found.
    jp c,ER_SYNTX       ;#2DB3  Otherwise, jump to syntax error handler.

DS_SAVE05               ;#2BE3
; Save CODE type block of bytes.
    call PARAM_C        ;#2E82  Evaluate parameters for SAVE <n$>CODE.
    ld hl,(VAR_B)       ;       Put start address of block into (VAR_A).
    ld (VAR_A),hl
    ld hl,(VAR_C)       ;       Put length of block of bytes into (VAR_C).
    ld (VAR_B),hl

DS_SAVE06               ;#2BF2
    call SYN_CHCK       ;#2E0E  Return if DOS is in syntax checking mode.
    ld a,"C"            ;       Assign CODE type file to (FILETYPE).
    ld (FILETYPE),a
    call FILEXIST       ;#2B68  Check if file already exists and there is space
                        ;       in the directory.
DS_SAVE07               ;#2BFD
    call SAVEFILE       ;#2C03  Save file into disk.
    jp DIR_RET          ;#24E6  Jump backward to update directory entry.

;------------------------------------------------------------------------------
; Subroutine: SAVE FILE
; Address: #2C03/11267
; Save file into disk.
; Input: (VAR_A)=parameter 1 field of directory entry;
;        (VAR_C)=parameter 2 field of directory entry;
;        (VAR_B)=length of file;
;        (NODISK)=line number of auto starting program.
; Called by: DS_SAVE, SV_SGMT.
;------------------------------------------------------------------------------
SAVEFILE                ;#2C03
    ld hl,(VAR_A)       ;       Copy VAR_A content to FILEPARM1.
    ld (FILEPARM1),hl
    ex de,hl
    ld hl,(VAR_B)       ;       HL=file length.
    ld a,l              ;       Jump to syntax error handler if length is null.
    or h
    jp z,ER_SYNTX       ;#2DB3 　
    ld a,l              ;       Jump forward if LSB of length is 0; otherwise, 
    or a                ;       incremente MSB of length (this is done to 
    jr z,SAVEFILE01     ;#2C17  calculate number of sectors necessary to save 
    inc h               ;       the file).

SAVEFILE01              ;#2C17
    ld a,h              ;       Store resulting number of sectors (i.e., blocks 
    ld (FILESIZE),a     ;       of 256 bytes of data) into FILESIZE.
    ld e,a              ;       Calculate new value of number of free sectors:
    ld d,0              ;       HL=(BUFFER+CS_NFREE)-(FILESIZE). Note: C flag
    ld hl,(BUFFER+CS_NFREE) ;   =0 owing to past 'or a' instruction.
    sbc hl,de           ;       Raise 'no space' error condition if resulting 
    jp c,ER_NOSPACE     ;#2CE0  value is negative.
    push hl             ;       Stack number of free sectors.
    ld hl,(E_LINE)      ;       Set pointer to line editor space.
    ld (hl),#AA         ;       Put #AA separator.
    inc hl              ;       Increment pointer.
    ld de,(NODISK)      ;       Fetch auto-starting line number of BASIC.
    ld (hl),e           ;       Store this number in the next positions of line
    inc hl              ;       editor.
    ld (hl),d    
    ld hl,(VAR_C)       ;       Copy VAR_C content into FILEPARM2.
    ld (FILEPARM2),hl
    ld hl,(BUFFER+CS_FREES) ;  Take start sector/track ID of free disk space 
    ld (FILESECT),hl    ;       and  copy to start sector/track ID of file.
    push hl             ;       Stack start sector/track ID.
    call LOADBUFF01     ;       Restore contents of printer buffer.
    pop hl              ;       Unstack start sector/track ID.
    ex de,hl            ;       D=start track, E=start sector.
    ld hl,(FILEPARM1)   ;       HL=start address of data to save (note: for 
    ld a,(FILESIZE)     ;       stream files, address is in ROM).
    ld b,a              ;       B=number of sectors occupied by the file.
    call WRSECTORS      ;#2EFA  Write file body data into disk.
    ld hl,(RWSECID)     ;       Fetch sector/track position just after the last 
    push hl             ;       sector written to disk and save onto stack.
    call READ_CS        ;#237F  Read configuration sector from disk and save 
                        ;       into printer buffer.
    pop hl              ;       Unstack sector/track position and store into
    ld (BUFFER+CS_FREES),hl ;   CS_FREES field of configuration sector.
    pop hl                  ;   Unstack number of free sectors and store into
    ld (BUFFER+CS_NFREE),hl ;   CS_NFREE configuration sector field.
    ld hl,BUFFER+CS_NFILE
    ld a,(hl)           ;       Take number of files in the disk and assign it
    ld (FILEPOS),a      ;       as the position of file entry in directory.
    inc (hl)            ;       Increment number of files.
    push hl             ;       Save pointer to BUFFER+CS_NFILE onto stack.
    call WRT_BUFFER     ;#2EF0  Write configuration sector to disk.
    pop hl              ;       Unstack BUFFER+CS_NFILE address.
    ld c,(hl)           ;       C=position of entry in the directory.
    dec c    
    ld a,(FILETYPE)     ;       Call subroutine to calculate parameter for 
    cp "B"              ;       BASIC if type is "B".
    call z,SIZE_BAS     ;#2C77
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: SIZE of BASic
; Address: #2C77/11383
; BASIC program have slightly differente meaning for parameters 1 and 2 in the
;directory entry, so requires its own subroutine to evaluate these values.
; Output: (FILEPARM1)=total length of file (BASIC program + variables);
;         (FILEPARM2)=length of BASIC program only.
; Called by: SAVEFILE.
;------------------------------------------------------------------------------
SIZE_BAS                ;#2C77
    ld hl,(E_LINE)      ;       Evaluate total lenght of file:
    ld de,(PROG)        ;       HL=(E_LINE)-(PROG)-1
    scf                 ;       and store as file parameter 1.
    sbc hl,de
    ld (FILEPARM1),hl
    ld hl,(VARS)        ;       Evaluate length of BASIC program without 
    sbc hl,de           ;       variables: HL=(VARS)-(PROG)
    ld (FILEPARM2),hl   ;       and store as file parameter 2.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: PARAMeters for Basic
; Address: #2C8D/11405.
; Evaluate parameters for BASIC program saving.
; Input:  C flag=0.
; Output: (VAR_A)=start address of BASIC program;
;         (VAR_C)=length of BASIC program (without variables);
;         (VAR_B)=total length of file.
; Note: this routine works correctly only with C flag=0 at entry point; this 
;happens because DS_SAVE calls BAS_RMFP before PARAM_B.
; Called by: DS_SAVE.
;------------------------------------------------------------------------------
PARAM_B                 ;#2C8D
    ld hl,(VARS)        ;       Calculate length of BASIC program with:
    ld de,(PROG)        ;       (VAR_C)=(VARS)-(PROG).
    sbc hl,de           ;       It's supposed that C flag is 0.
    ld (VAR_C),hl       ;       Store this parameter in (VAR_C).
    ld hl,(PROG)        ;       Store start address of BASIC program in 
    ld (VAR_A),hl       ;       (VAR_A).
    ld hl,(E_LINE)      ;       Calculate total lenght to save, including BASIC
    inc hl              ;       program, variables and space for separator and 
    inc hl              ;       autostart line number with:
    inc hl              ;       (VAR_B)=(E_LINE)-(PROG)+3.
    sbc hl,de
    ld (VAR_B),hl       ;       Store this parameter in (VAR_B).
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: FETch ARRAY
; Address: #2CAB/11435
; Fetch array data.
; Output: (VAR_A)=start address of array;
;         (VAR_C)=length of array data;
;         (VAR_B)=length of array data or 0 if not found;
;         C flag=0 if array was found;
;         (VARNAME)=1 byte ID of array.
; Called by: LOADARG.
;------------------------------------------------------------------------------
FETARRAY                ;#2CAB
    call PARAM_D        ;#2CB6  Seek for array and, if it is found, fetch its 
    ret nc              ;       informations and return.
    ld hl,0             ;       Otherwise, assign null length for array.
    ld (VAR_B),hl
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: PARAMeters for Data
; Address: #2CB6/11446
; Evaluate parameters for DATA type array.
; Output: (VAR_A)=start address of array;
;         (VAR_C)=length of array data;
;         (VAR_B)=length of array data;
;         C flag=0 if array was found;
;         (VARNAME)=1 byte ID of array.
; Called by: DS_SAVE, FETARRAY. 
;------------------------------------------------------------------------------
PARAM_D                 ;#2CB6
    call BAS_NXTCHR     ;#2ECB  Move cursor to position after 'DATA' token.
    call BAS_LKVAR      ;#2E3B  Look for variable pointed by CH_ADD.
    set 7,c             ;       Type of string variable is changed to array of 
    ld a,c              ;       strings and stored into DOS system variable.
    ld (VARNAME),a
    jr nc,PARAM_D02     ;#2CC6  Jump forward if variable was found.

PARAM_D01               ;#2CC4
    scf                 ;       Variable was not found, C flag=1 and return.
    ret

PARAM_D02               ;#2CC6
    jr nz,PARAM_D01     ;#2CC4  Jump backward if variable is not an array.
    inc hl              ;       Increment pointer.
    ld e,(hl)           ;       Get length of array.
    inc hl    
    ld d,(hl)    
    inc hl              ;       HL points to number of dimensions of array.
    ld (VAR_A),hl       ;       Store pointer.
    ld (VAR_C),de       ;       Store length.
    ld (VAR_B),de       ;       Store length.
    call BAS_NXTCHR     ;#2ECB  Fetch next character in the command line.
    cp ")"              ;       Jump backward (first to PARAM_D01 and then to 
    jr nz,PARAM_D02     ;#2CC6  PARAM_D02) if ")" is not found.
    ret                 ;       Return with C flag=0.

;-----------------------------------------------------------------------------
; Error routine: NO SPACE
; Address: #2CE0/11488
; Disk has no enough free space (but COPYFILE raise this error when there is no 
;space in the directory).
; Called by: COPYFILE, SAVEFILE.
;-----------------------------------------------------------------------------
ER_NOSPACE              ;#2CE0
    ld hl,M_NOSPACE     ;#3960  Message: "No space".
    ld a,3              ;       DOS error code 3.
;==============================================================================
; Routine: Dos STateMent ERror RETurn
; Address: #2CE5/11493
; Return point after an error raised during DOS statement operation. Print 
;error message only in DOS CLI mode.
; Called by: ER_NOSPACE, ER_F_EXIST, ER_STMOPEN, ER_NODISK, ER_DIRFULL, 
;ER_NOFILE, ER_OVERFL.
;==============================================================================
DSTM_ERRET              ;#2CE5
    call PRINTERR       ;#2342  Print error message only in DOS CLI mode.
    jp DSTM_RET         ;#2170  Return to DOS interpreter.

;-----------------------------------------------------------------------------
; Error routine: File EXISTs
; Address: #2CEB/11499
; A file with same name already exists in the directory.
; Called by: DS_NEW, FILEXIST.
;-----------------------------------------------------------------------------
ER_F_EXIST              ;#2CEB
    ld hl,M_F_EXIST     ;#396A  Message: "File exists".
    ld a,2              ;       DOS error code 2.
    jr DSTM_ERRET       ;#2CE5  Jump to error handler.

;------------------------------------------------------------------------------
; Subroutine: GET File NAME
; Address: #2CF2/11506
; Fetch string information from calculator stack and store into FILENAME DOS
;system variable. Drive ID prefix ("X:filaname") will change current drive. 
;Any string longer than 8 bytes will be truncated and shorter string will be
;padded with 'space' characters.
; Called by: SEEKFILE, DS_FORMAT, USTK_FILE.
;------------------------------------------------------------------------------
GET_FNAME               ;#2CF2
    ld hl,FILENAME      ;       HL is pointer for DOS system variable.
    ld b,8              ;       Filename length is 8 bytes.

GET_FNAME01             ;#2CF7
    ld (hl),#20         ;       Clear FILENAME, filling 8 bytes of 'space' 
    inc hl              ;       characters.
    djnz GET_FNAME01    ;#2CF7 
    call USTK_STR       ;#2498  Unstack string data from calculator stack and 
    ex de,hl            ;       define HL as pointer to it.
    call GET_DRV        ;#2D1A  Check for the presence of drive descriptor in
                        ;       the string and change current drive.
    ld a,c              ;       C is length of string.
    or a                ;       Raise syntax error if string length became 0.
    jp z,ER_SYNTX       ;#2DB3 
    cp 9                ;       Jump and skip next instruction if string length 
    jr c,GET_FNAME02    ;#2D0E  is less than 8 bytes.
    ld c,8              ;       Otherwise, trucate string to 8 bytes.

GET_FNAME02             ;#2D0E
    ld a,(hl)           ;       Any character less than 'space' in the first 
    cp #20              ;       byte of filename will raise syntax error 
    jp c,ER_SYNTX       ;#2DB3  condition.
    ld de,FILENAME      ;       Copy C bytes of string to FILENAME system 
    ldir                ;       variable.
    ret                 ;       End of subroutine.
  
;------------------------------------------------------------------------------
; Subroutine: GET DRiVe
; Address: #2D1A/11546
; Some statements accepts drive letter followed by colon at the start of a
;string type argument (like "A:filename"). This subroutine parses a string 
;entered as argument and, if the second byte is ":", changes current drive.
; Input:  HL=start address of string;
;         BC=length of string.
; Output: (CURRDRIVE)=current drive number (0-3).
;         HL=address of string skipping "X:" drive letter and colon;
;         BC=length of string without "X:".
; Called by: DS_CAT, COPYALL, GET_FNAME. 
;------------------------------------------------------------------------------
GET_DRV                 ;#2D1A
    inc hl              ;       Get next character code.
    ld a,(hl)
    cp ":"              ;       Character other than 'colon' does not refer to 
    jr nz,GET_DRV01     ;#2D31  drive letter; jump to keep current drive.
    dec hl              ;       Decrement pointer to its previous value.
    ld a,(hl)           ;       Get character.
    call DRIVENUM       ;#248B  Convert to drive number.
    push bc             ;       Stack string length.
    push hl             ;       Stack string pointer.
    call SEL_DRIVE01    ;#3D74  Change current drive.
    pop hl              ;       Unstack string pointer.
    pop bc              ;       Unstack string length.
    dec bc              ;       Decrement length and advance pointer two 
    dec bc              ;       positions to skip "X:" drive descriptor in the 
    inc hl              ;       string.
    inc hl    
    ret                 ;       End of subroutine.

GET_DRV01               ;#2D31
    dec hl              ;       Decrement pointer to its previous value.
    ld a,(DEFLTDRV)     ;       Drive number will be the current one.
    push bc             ;       Stack string length.
    push hl             ;       Stack string pointer.
    call SEL_DRIVE01    ;#3D74  Select current drive.
    pop hl              ;       Unstack string pointer.
    pop bc              ;       Unstack string length.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: DIRectory ENTRY POSition
; Address: #2D3D/11581
; Evalute from directory entry number (0-15) the address of entry in the 
;printer buffer memory. Value greater than 15 produces address above printer
;buffer area (>23551).
; Input:  C=directory entry number (0-15).
; Output: HL=address of entry.
; Called by: SEEKFILE, CP_ENTRY. 
;------------------------------------------------------------------------------
DIRENTRYPOS             ;#2D3D
    ld l,c              ;       HL=directory entry number (0-127)
    ld h,0
    add hl,hl           ;       HL=16*HL
    add hl,hl
    add hl,hl
    add hl,hl
    ld bc,BUFFER
    add hl,bc           ;       HL=HL+BUFFER 
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: SEEK FILE
; Address: #2D49/11593
; Seek in the directory for a file with same name and type and, for a stream 
;file, with same data segment. 
; Input:  (top of calculator stack)=file descriptor string
; Output: Z flag=1 (file found);
;               =0 (file not found);
;         C=position of file entry within directory (0-127);
;         (FILEPOS)=position of file entry within directory.
; Called by: SEEKSTRM, DS_NEW, DS_COPY.
;------------------------------------------------------------------------------
SEEKFILE                ;#2D49
    call GET_FNAME      ;#2CF2  Get filename from calculator stack.

;------------------------------------------------------------------------------
; SEEKFILE01 (#2D4C/11596)
; This entry point uses filename from DOS system variable 'FILENAME'.
; Called by: #2D80, SEEKSTRM, SEEKNXTSEG, RNDRECORD, USTK_FILE, SEEK_STRF, 
;COPYALL, ERASEFILE.
;------------------------------------------------------------------------------
SEEKFILE01              ;#2D4C
    call READT0S0       ;#2360  Read first sector of disk directory.
    ld b,128            ;       Counter for 128 entries.
    ld c,0              ;       Number of directory entry.

SEEKFILE02              ;#2D53
; This routine reads one sector of directory at a time, containing 16 entries.
;SEEKFILE02 loop ensures that next sector will be read when pointer exceeds the 
;last entry of the current sector.
    push bc             ;       Stack entry counter/entry number.
    call DIRENTRYPOS    ;#2D3D  Compute address of directory entry.
    call NXTDIRSEC      ;#2473  When C=16 the limit of one sector is exceeded
                        ;       and the next directory sector is read into 
                        ;       printer buffer.
    pop bc              ;       Unstack entry counter/entry number.
    push bc             ;       Stack entry counter/entry number.
    ld a,c
    cp 16               ;       Jump forward if entry number did not reach 
    jr nz,SEEKFILE03    ;#2D66  limit (i.e., C<16); otherwise, reset C and 
                        ;       recalculate address of entry at new sector.
    pop bc              ;       Unstack entry counter/entry number.
    ld c,0
    jr SEEKFILE02       ;#2D53  Jump backwart to the loop.

SEEKFILE03              ;#2D66
    ld de,FILENAME      ;       DE is pointer of FILENAME system variable.
    ld a,(CMP_SIZE)     ;       Fetch number of bytes to compare (9 or 10).
    ld b,a              ;       B is counter for number of bytes to compare.
    xor a               ;       A=0.
    cp (hl)             ;       Jump forward if end of directory marker (0) is 
    jr nz,SEEKFILE04    ;#2D74  not found.
    pop bc              ;       Unstack entry counter/entry number.
    jr SEEKFILE05       ;#2D7D  Jump forward.

SEEKFILE04              ;#2D74
    call CP_STRING      ;#3787  Compare directory entry and FILENAME contents.
    pop bc              ;       Unstack entry counter/entry number.
    jr z,SEEKFILE06     ;#2D80  Jump forward if comparison was successful, i.e.
    inc c               ;       i.e. file was found.; otherwise, increment 
    djnz SEEKFILE02     ;#2D53  entry number and repeat until all 128 entries
                        ;       of disk is compared.
SEEKFILE05              ;#2D7D
; File was not found, return with Z flag=0.
    or #FF              ;       Z flag=0 (end of directory was reached and file
                        ;       was not found). 
    ret                 ;       Exit subroutine.

SEEKFILE06              ;#2D80
; File was found, return with Z flag=1.
    ld a,128            ;       C=B-128, C contains position of entry in the 
    sub b               ;       directory (0-127).
    ld c,a    
    ld (FILEPOS),a      ;       Store entry position into DOS system variable.
    xor a               ;       Z flag=1.
    ret z               ;       Always return since Z flag=1.

; Following code is never executed.
    call SEEKFILE01     ;#2D4C 
    ld hl,D_ERRCOD
    ld (hl),c    
    ret z    
    ld (hl),#FF
    ret    

;==============================================================================
; DOS Statement: RETURN
; Address: #2D94/11668
; Return from DOS command line interface and give control of computer to the
;Sinclair BASIC monitor.
; Note: 'USR 15360' must be used to go back to DOS command line interface from
;BASIC monitor.
; Syntax: RETURN
;==============================================================================
DS_RETURN               ;#2D94
    call SYN_CHCK       ;#2E0E  Return if DOS is in syntax checking mode.
    call IF1VSWP        ;#318C  Restore Interface 1 system variables.
    res 3,(iy+1)        ;       Line editor cursor will be in "K" mode.
    call RST_ERRSP      ;#21D5  Fetch saved value of ERR_SP.
    ld sp,(OLDSP)       ;       Restore previous value of stack pointer.
    ld hl,(ERR_SP)      ;       HL points to error return address.
    dec hl              ;       Check if MSB of the stack element below the one
    ld a,#12            ;       pointed by ERR_SP (MAIN-4 BASIC routine) is 
    cp (hl)             ;       #12. 
    jr nz,DS_RETURN01   ;#2DB2  Jump and return to BASIC if byte is not #12.
    dec hl              ;       Otherwise, this stack element is likely to be 
    ld (ERR_SP),hl      ;       #128B (BASIC routine that prints Sinclair logo) 
                        ;       and is adopted as new position pointed by 
                        ;       ERR_SP (see RESET-08).
DS_RETURN01             ;#2DB2
    ret                 ;       Return to BASIC monitor.

;------------------------------------------------------------------------------
; Error routine: SYNTaX
; Address: #2DB3/11699
; Handle syntax error detected during command line scan.
; Called by: DS_CAT, DRIVENUM, DS_NEW, COPYALL, DS_MERGE, SCT_OFF, DS_SAVE, 
;SAVEFILE, GET_FNAME, DOSERROR01, GETARG_CS, PARAM_C, DS_FORMAT, RND_ARG, 
;DS_OPEN, DS_40.
;------------------------------------------------------------------------------
ER_SYNTX                ;#2DB3
    bit 7,(iy+0)        ;       Any positive error code (with bit 7=0) force 
    jr z,ER_SYNTX01     ;#2DBE  jump forward to skip next 2 instructions.
    ld a,11             ;       Negative error code (mainly #FF/-1) will be 
    ld (ERR_NR),a       ;       replaced by error 11 (C-Non sense in BASIC).

ER_SYNTX01              ;#2DBE
    inc a               ;       Increment code to be DOS error code.
    ld hl,M_ERROR       ;#3957  Address of message "*ERROR*".

;------------------------------------------------------------------------------
; Routine: ERROR RETurn
; Address: #2DC2/11714
; Print error message if DOS is in CLI mode and return from DOS statement.
; Called by: ER_SYNTX, DOSERROR01, WRSECTORS.
;------------------------------------------------------------------------------
ERROR_RET               ;#2DC2
    call PRINTERR       ;#2342  Print error message only in DOS CLI mode.
    jp DSTM_RET         ;#2170  Return from DOS statement.

;------------------------------------------------------------------------------
; DOSERROR01 (#2DC8/11720). 
; Part of DOSERROR routine (#3C15/15381). 
; Check error code and handle when BREAK key was pressed or RAM is out. Other
;errors are handled as syntax error.
;------------------------------------------------------------------------------
DOSERROR01              ;#2DC8
    ld a,(ERR_NR)       ;       Fetch error code.
    ld hl,M_BREAK       ;#37AD  Message: "*BREAK*".
    cp 20               ;       Jump to print error message if error code 20 
    jr z,ERROR_RET      ;#2DC2  (BREAK has been pressed).
    cp 12               ;       Jump to print error message if error code 12 
    jr z,ERROR_RET      ;#2DC2  (BREAK has been pressed).
    ld hl,M_OUT_RAM     ;#37B5  Error message for insufficient memory.
    cp 3                ;       Jump to print error message if error code 3 
    jr z,ERROR_RET      ;#2DC2  (not enough memory to carry out operation).
    jr ER_SYNTX         ;#2DB3  For other errors, assume syntax error.

;==============================================================================
; DOS Statement: RUN 
; Address: #2DDF/11743
; Load and run a BASIC or machine code program. 
; Syntax: RUN [n$]
;         RUN <n$> CODE [addr]
; (n$=filename, addr=start address and execution address of block to load)
;==============================================================================
DS_RUN                  ;#2DDF
    call RS_LDEXEC      ;#2981  Set flag to LOAD/SAVE type statement.  
    call FILELOAD       ;#2965  Load BASIC or machine code block of bytes.
    call SYN_CHCK       ;#2E0E  Return if DOS is in syntax checking mode.
    ld hl,(FILEPARM1)   ;       HL=start address of machine code.
    ld a,(FILETYPE)     ;       Check if file is "B" (BASIC) type.
    cp "B"
    jp z,EXEC_BAS       ;#20F1  Jump to run BASIC program if type is "B",
                        ;       otherwise prepare to run machine code.
    push hl             ;       Stack machine code start address.
    ld hl,DSTM_RET      ;#2170  Stack DOS interpreter return address.
    push hl             ;       Stack DOS statement execution return address.
    jp CALLBAS1         ;#3C50  Jump to CALLBAS1 to enable BASIC ROM, execute 
                        ;       machine code program and return to DOS 
                        ;       interpreter.

;------------------------------------------------------------------------------
; Subroutine: BASic SET-WORK
; Address: #2DFB/11771
; Clear workspace and calculator stack if (CLR_WSP) is not #FF.
; Output: (CLR_WSP)=0.
; Called by: DSTM_RET.
;------------------------------------------------------------------------------
BAS_SETW                ;#2DFB
    ld hl,CLR_WSP       ;       Check value of CLR_WSP system variable.
    ld a,(hl)
    cp #FF
    ld (hl),0           ;       Zero value of CLR_WSP system variable.
    ret nz              ;       Finish if CLR_WSP is not #FF; otherwise, call 
    ld hl,#16BF         ;       SET-WORK subroutine from BASIC ROM.
    jr CALLBAS          ;#2E36 

;------------------------------------------------------------------------------
; Subroutine: test Bit 7 of FLAGS
; Address: #2E09/11785
; Test bit 7 value of FLAGS (1=line execution; 0=syntax checking).
; Output: Z flag=state of bit 7 of FLAGS.
; Called by: SYN_CHCK, GETARG_N.
;------------------------------------------------------------------------------
B7_FLAGS                ;#2E90
    bit 7,(iy+1)        ;       Test bit 7 of FLAGS.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: SYNtax CHeCK 
; Address: #2E0E/11790
; Verify status of DOS interpreter. When bit 7 of FLAGS is high, DOS is 
;executing a statement; this subroutine simply return with Z flag rised.
;When bit 7 is low, DOS is performing a syntax check; this subroutine discard
;return address of top of stack and jump to address of next stack element.
; Output: Z flag=state of bit 7 of FLAGS.
; Called by: DS_CAT, DS_DRV, DS_NEW, DS_COPY, DS_ERASE, DS_MOVE, PEEKPOKE01, 
;FILELOAD, LOADARG, DS_MERGE, DS_SAVE, DS_RETURN, DS_RUN, PARAM_C01, DS_FORMAT,
;RND_ARG, DS_OPEN, DS_CLOSE, DS_80_01, DS_GOTO.
;------------------------------------------------------------------------------
SYN_CHCK                ;#2E0E
    call B7_FLAGS       ;       Test bit 7 of FLAGS.
    ret nz              ;       Finish if it was 1.
    pop hl              ;       Remove return address from stack if bit 7 was 0. 
    ret                 ;       Jump to address of next stack element.

;------------------------------------------------------------------------------
; Subroutine: GET ARGument Numeric
; Address: #2E14/11796
; Evaluate numeric argument from command line and put resulting value onto
;calculator stack. 
; Output: Z flag=status of bit 7 of FLAGS.
; Called by: PARAM_C, GETARG_I.
;------------------------------------------------------------------------------
GETARG_N                ;#2E14
    call BAS_NXTCHR     ;#2ECB  Fetch next character of line.
    call BAS_E1NUM      ;#2E5D  Evaluate numeric argument.
    jr B7_FLAGS         ;#2E90  Test bit 7 of FLAGS and return.

;------------------------------------------------------------------------------
; Subroutine: OPEN K channel 
; Address: #2E1C/11804
; Open "K" channel (stream #0). Printing will be redirected to the lower lines 
;of screen.
; Called by: DOS_CLI03, BAS_EDITOR, 
;------------------------------------------------------------------------------
OPEN_K                  ;#2E1C
    xor a               ;       A=0, code of "K" channel.

;------------------------------------------------------------------------------
; Subroutine: BASic OPEN
; Address: #2E1D/11805
; Open channel with code specified by the accumulator.
; Called by: DS_CAT, OPEN_K, OPEN_S. 
;------------------------------------------------------------------------------
BAS_OPEN                ;#2E1D
    ld hl,#1601         ;       Address of CHAN-OPEN routine (#1601/5633).
    jr CALLBAS          ;#2E36  Call routine from BASIC ROM.

;------------------------------------------------------------------------------
; Subroutine: OPEN S channel 
; Address: #2E22/11810
; Open "S" channel (strem #2). Printing will be redirected to the upper lines 
;of screen.
; Called by: DOS_CLI02. 
;------------------------------------------------------------------------------
OPEN_S                  ;#2E22
    ld a,2              ;       Code of "S" channel is 2.
    jr BAS_OPEN         ;#2E1D  Open channel.

;------------------------------------------------------------------------------
; Subroutine: BASic GET-CHAR
; Address: #2E26/11814
; Call GET-CHAR (RST #18) from ROM BASIC. Seek a printable character starting
;for the position pointed by CH-ADD. A register will contain code of the 
;character and CH-ADD will be update if neccessary.
; Called by: FET_ENTER, DS_CAT, FIND_FTYPE, LOADARG, DS_SAVE, DS_SAVE, 
;GETARG_CS, PARAM_C, #2E98, RND_ARG, DS_OPEN. 
;------------------------------------------------------------------------------
BAS_GETCHR              ;#2E26
    ld hl,#18           ;       Address of RST #18 subroutine (#0018/24).
    jr CALLBAS          ;#2E36  Call BASIC ROM routine.

;------------------------------------------------------------------------------
; Subroutine: BASic EDITOR
; Address: #2E2B/11819
; Call the line editor of BASIC ROM.
; Called by: EDITLINE. 
;------------------------------------------------------------------------------
BAS_EDITOR              ;#2E2B
    call OPEN_K         ;#2E1C  Print output is redirected to lower lines of 
                        ;       the screen.
    ld hl,#0F2C         ;       Address of EDITOR routine (#0F2C/3884).
    jr CALLBAS          ;#2E36  Call routine from BASIC ROM.

;------------------------------------------------------------------------------
; Subroutine: BASIC CLS
; Address: #2E33/11827
; Call CLS subroutine from BASIC ROM. Clear screen.
; Called by: EXEC_BAS, DOS_CLI02, DS_CAT, OVERWRITE, RDWRSECT. 
;------------------------------------------------------------------------------
BAS_CLS                 ;#2E33
    ld hl,#0D6B         ;       Address of CLS subroutine (#0D6B/3435).
                        ;       Continue to CALL_BAS routine.

;------------------------------------------------------------------------------
; Subroutine: CALL BASic
; Address: #2E36/11830
; Execute a routine from BASIC ROM located at address specified by HL. Enable
;BASIC ROM temporarily, call the routine and return to ROM_BASIC subroutine.
; Called by:  RESET08, EXEC_BAS, READKEY, CHECKRAM, DS_MERGE, TESTSPACE, 
;BAS_SETW, GETARG_N, BAS_OPEN, OPEN_S, BAS_GETCHR, BAS_EDITOR, BAS_CLS 
;BAS_LKVAR, BAS_CLSLOW, BAS_STKFET, BAS_FDINT, BAS_EEXP, BAS_E1NUM, VRF_STRM, 
;ER_ENDFILE, DS_CLOSE, BAS_PRNTBC, BAS_RST16, FDC_CMD.
;------------------------------------------------------------------------------
CALLBAS                 ;#2E36
    push hl             ;       Store BASIC routine address onto stack.    
    call CALLBAS1       ;#3C50  Main subroutine resides at region 15360-15615/
    ret                 ;       #3C00-#3CFF region; thus, it is visible even 
                        ;       when BASIC ROM is enabled.

;------------------------------------------------------------------------------
; Subroutine: BASIC LooK-VARs
; Address: #2E3B/11835
; Search a BASIC variable which name is pointed by CH_ADD system variable.
; Output: C flag=0 if variable found;
;         Z flag=1 if variable is string or array;
;         HL=address of variable letter.
; Called by: PARAM_D. 
;------------------------------------------------------------------------------
BAS_LKVAR               ;#2E3B
    ld hl,#28B2         ;       Address of LOOK-VARS subroutine (#28B2/10418).
    jr CALLBAS          ;#2E36  Call BASIC ROM routine.

;------------------------------------------------------------------------------
; Subroutine: BASic CLS LOW
; Address: #2E40/11840
; Clear lower lines of screen.
; Called by: DOS_CLI03. 
;------------------------------------------------------------------------------
BAS_CLSLOW              ;#2E40
    ld hl,#0D6E         ;       Address of CLS-LOW subroutine (#0D6E/3438).
    jr CALLBAS          ;#2E36  Call BASIC ROM routine.

;------------------------------------------------------------------------------
; Subroutine: BASic PRiNT BC
; Address: #2E45/11845
; Print number of BC register pair within 0-9999 range.
; Called by: FILEENTRY01, DS_CAT, DS_FORMAT, PRINTN_C. 
;------------------------------------------------------------------------------
BAS_PRNTBC              ;#2E45
    call SAVECFGS       ;#3918  Save configuration sector data in the printer 
                        ;       before calling BASIC print routine.
    ld hl,#1A1B         ;       Address of OUT-NUM-1 subroutine (#1A1B/6683).
    jp BAS_PRNTBC01     ;#3912  Jump forward to complete printing.

;------------------------------------------------------------------------------
; Subroutine: BASic STK-FETch
; Address: #2E4E/11854
; Fetch 5 bytes from top of calculator stack.
; Output: registers A,E,B,C,D contain 5 bytes fetched from stack.
; Called by: DS_CAT, USTK_STR, COPYALL. 
;------------------------------------------------------------------------------
BAS_STKFET              ;#2E4E
    ld hl,#2BF1         ;       Address of STK-FETCH subroutine (#2BF1/11249).
    jr CALLBAS          ;#2E36  Call BASIC ROM routine.

;------------------------------------------------------------------------------
; Subroutine: BASic FinD-INT2
; Address: #2E53/11859
; Fetch last item of calculator stack, convert to integer and pass to BC.
; Called by: PARAM_C, GETARG_I, GETRECORD.
;------------------------------------------------------------------------------
BAS_FDINT               ;#2E53
    ld hl,#1E99         ;       Address of FIND-INT2 subroutine (#1E99/7833).
    jr CALLBAS          ;#2E36  Call BASIC ROM routine.

;------------------------------------------------------------------------------
; Subroutine: BASic Expt-EXP
; Address: #2E58/11864
; Evaluate string expression within a line. Once a valid string is found, it
;is put onto calculator stack coded in 5-bytes: byte 1=unused; bytes 2-3=
;start address; bytes 4-5=length. Employed for evaluation of a DOS statement 
;argument.
; Called by: GET2ARG_S, GET1ARG_S, DS_CAT.
;------------------------------------------------------------------------------
BAS_EEXP                ;#2E58
    ld hl,#1C8C         ;       Address of EXPT-EXP subroutine (#1C8C/7308).
    jr CALLBAS          ;#2E36  Call BASIC ROM routine.

;------------------------------------------------------------------------------
; Subroutine: BASic Expt-1NUM
; Address: #2E5D/11869
; Evaluate numeric expression within a line. The resulting value is put onto
;calculator stack. Employed for evaluation of a DOS statement argument.
; Called by: GETARG_N, GETRECORD. 
;------------------------------------------------------------------------------
BAS_E1NUM               ;#2E5D
    ld hl,#1C82         ;       Address of EXPT-1NUM subroutine (#1C82/7298).
    jr CALLBAS          ;#2E36  Call BASIC ROM routine.

;------------------------------------------------------------------------------
; Subroutine: DEFine CH_ADD
; Address: #2E62/11874
; Define DOS interpreter cursor address as the next byte after DOS statement
;in the line.
; Called by: GET1ARG_S.
;------------------------------------------------------------------------------
DEFCHADD                ;#2E62
    ld hl,(DSTMADDR)    ;       Get address of line with DOS statement.
    inc hl              ;       Define next byte as the interpreter cursor 
    ld (CH_ADD),hl      ;       address.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: GET 2 ARGuments String
; Address: #2E6A/11882
; Parse command line for a string type argument followed by comma and by a 
;second string. Both strings data will be stored on top of calculator stack.
; Called by: DS_NEW, DS_COPY.
;------------------------------------------------------------------------------
GET2ARG_S               ;#2E6A
    call GET1ARG_S      ;#2E7C  Get first argument on calculator stack. Then,
                        ;       get second argument after a comma.

;------------------------------------------------------------------------------
; Subroutine: GET ARGument after Comma String
; Address: #2E6D/11885
; Parse command line for a string after comma.
; Called by: GET2ARG_S, DS_OPEN.
;------------------------------------------------------------------------------
GETARG_CS               ;#2E6D
    call BAS_GETCHR     ;#2E26  Get next character from command line.
    cp ","              ;       Jump to syntax error handler if character is 
    jp nz,ER_SYNTX      ;#2DB3  not comma.
    call BAS_NXTCHR     ;#2ECB  Advance interpreter cursor to the next 
    call BAS_EEXP       ;#2E58  character position and get the 2nd string.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: GET 1 ARGument String
; Address: #2E7C/11900
; Get one argument of string type from line. String data is atop of calculator
;stack.
; Called by: DS_CAT, DS_DRV, DS_ERASE, LOADARG, DS_SAVE, GET2ARG_S, DS_FORMAT, 
;DS_GOTO.
;------------------------------------------------------------------------------
GET1ARG_S               ;#2E7C
    call DEFCHADD       ;#2E62  Place interpreter pointer at start of argument
    jp BAS_EEXP         ;#2E58  and evaluate a string.

;------------------------------------------------------------------------------
; Subroutine: PARAMeters for Code
; Address: #2E82/11906.
; Evaluate parameters for block of bytes type 'CODE'.
; Output: (VAR_B)=first argument (start address);
;         (VAR_C)=second argument (length) if any, or first argument.
;         (CODEARG)=3 if second argument was found.
; Called by: DS_SAVE.
;------------------------------------------------------------------------------
PARAM_C                 ;#2E82
    call BAS_GETCHR     ;#2E26  Get character from command line.
    cp 175              ;       Return if character is not 'CODE'.
    ret nz    

;------------------------------------------------------------------------------
; PARAM_C01 (#2E88/11912)
; This entry point skips 'CODE' keyword checking.
; Called by: LDCD_ARG, PK_ARG.
;------------------------------------------------------------------------------
PARAM_C01               ;#2E88
    call GETARG_N       ;#2E14  Get numeric argument.
    jr z,PARAM_C02      ;#2E98  Jump forward if in syntax checking mode.
    call BAS_FDINT      ;#2E53  Pass integer from calculator stack to BC.
    ld (VAR_B),bc       ;       Store integer to DOS system variables.
    ld (VAR_C),bc

PARAM_C02               ;#2E98
    call BAS_GETCHR     ;#2E26  Get character from command line.
    cp ","              ;       Evaluate argument and put in (VAR_C) if 
    jr z,GETARG_I       ;#2EA8  character is 'comma'.
    cp 13               ;       Raise syntax error condition if character is 
    jp nz,ER_SYNTX      ;#2DB3  not 'Enter' (end of line).
    call SYN_CHCK       ;#2E0E  Return if DOS is in syntax checking mode.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: GET ARGument Integer
; Address: #2EA8/11944
; Get numeric argument from command line, convert to integer and store into
;(VAR_C) system variable in execution mode (bit 7 of FLAGS=0).
; Output: (VAR_C)=16-bit integer value of argument;
;         (CODEARG)=3.
; Called by: RND_ARG, DS_OPEN, DS_CLOSE, DS_CAT, DS_SAVE, PARAM_C.
;------------------------------------------------------------------------------
GETARG_I                ;#2EA8
    call GETARG_N       ;#2E14  Get argument from line. Finish here in syntax
    ret z               ;       checking mode (bit 7 of FLAGS=1).
    call BAS_FDINT      ;#2E53  Pass integer from calculator stack to BC.
    ld (VAR_C),bc       ;       Store integer into (VAR_C).
    ld a,3              ;       Assign value 3 to DOS system variable (second
    ld (CODEARG),a      ;       numeric argument was found).
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: BASic ReMove-FP
; Address: #2EB9/11961
; Call REMOVE-FP subroutine from BASIC ROM. Remove floating point number code
;hidden in a BASIC line (#0E followed by 5 bytes). Line starting at address
;pointed by HL is analised until #0D (Enter) marker is found.
; Output: A=#0D/13 ('enter');
;         Z flag=1;
;         C flag=0.
; Called by: DSTM_RET, DS_SAVE. 
;------------------------------------------------------------------------------
BAS_RMFP                ;#2EB9
    ld hl,(DSTMADDR)    ;       HL=start address of line.
    rst 32              ;       Save content of HL.
    ld hl,#11A7         ;       REMOVE-FP address of BASIC ROM.
    jr CALLBASHL        ;#2ECF  Call BASIC ROM subroutine.

;------------------------------------------------------------------------------
; Subroutine: BASic BC-SPaCes
; Address: #2EC2/11970
; Call BC-SPACES (RST 48) subroutine from BASIC ROM. Open BC bytes in the 
;BASIC workspace.
; Input:  BC=size of space to open.
; Output: DE=start address of new space;
;         HL=last byte address of new space.
; Called by: WKSPMEM, MK16BYTES. 
;------------------------------------------------------------------------------
BAS_BCSPC               ;#2EC2
    ld hl,(WORKSP)      ;       HL=address of BASIC workspace.
    rst 32              ;       Save content of HL.
    ld hl,48            ;       BC-SPACES subroutine address.
    jr CALLBASHL        ;#2ECF  Call BASIC ROM subroutine.

;------------------------------------------------------------------------------
; Subroutine: BASic NEXT-CHAR
; Address: #2ECB/11979
; Call NEXT-CHAR (RST 32) subroutine of BASIC ROM. Fetch next character of a
;BASIC line. Update CH_ADD.
; Called by: FET_ENTER, DS_CAT, PARAM_D, GETARG_N, GETARG_CS, RND_ARG, DS_OPEN. 
;------------------------------------------------------------------------------
BAS_NXTCHR              ;#2ECB
    rst 32              ;       Save content of HL.
    ld hl,32            ;       Address of NEXT-CHAR. This subroutine continues 
                        ;       in CALLBASHL.

;------------------------------------------------------------------------------
; Subroutine: CALL BASic saving HL
; Address: #2ECF/11983
; Execute BASIC ROM subroutine after recovering HL value saved at HLTEMP. Does
;not have the limitation of CALLBAS that destroys HL value.
; Input: HL=address of BASIC ROM subroutine.
; Called by: DS_MERGE, MKBASROOM, BAS_RMFP, BAS_NXTCHR, BAS_BCSPC, BAS_RECLM,
;BAS_MKROOM. 
;------------------------------------------------------------------------------
CALLBASHL               ;#2ECF
    push hl             ;       Save address of BASIC subroutine.
    ld hl,(HLTEMP)      ;       Restore HL to the previously saved value.
    call CALLBAS1       ;#3C50  Call BASIC subroutine.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: BASic RECLaiM-2
; Address: #2ED7/11991
; Call RECLAIM-2 subroutine of BASIC ROM. Reclaim RAM space from BASIC area and
;update memory separation system variables.
; Input:  HL=start address of memory to reclaim;
;         BC=number of bytes do reclaim.
; Called by: DS_MOVE, MKARRROOM, DS_CLOSE. 
;------------------------------------------------------------------------------
BAS_RECLM               ;#2ED7
    rst 32              ;       Save content of HL.
    ld hl,#19E8         ;       Address of RECLAIM-2 subroutine.
    jr CALLBASHL        ;#2ECF  Call BASIC ROM subroutine.

;------------------------------------------------------------------------------
; Subroutine: BASic MaKe-ROOM
; Address: #2EDD/11997
; Call MAKE-ROOM subroutine of BASIC ROM. Create an empty space into BASIC 
;area and update memory separation system variables.
; Input:  HL=(start address of new space)+1;
;         BC=number of bytes to open.
; Output: HL=(start address of new space)-1;
;         DE=end address of new space.
; Called by: MKBASROOM, MKARRROOM, MKNEWCHAN. 
;------------------------------------------------------------------------------
BAS_MKROOM              ;#2EDD
    rst 32              ;       Save content of HL.
    ld hl,#1655         ;       Address of MAKE-ROOM subroutine.
    jr CALLBASHL        ;#2ECF  Call BASIC ROM subroutine.

;------------------------------------------------------------------------------
; Subroutine: CURRent TRACK
; Address: #2EE3/12003
; Update FDC track register with the value read from disk.
; Called by: RW_SECTORS, LDSVBUFF02, SEL_DRIVE.
;------------------------------------------------------------------------------
CURRTRACK               ;#2EE3
    call READTRACK      ;#3E4F  Read current track number from disk.
    ld a,h              ;       Send read value to FDC track register.
    out (63),a
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: ReaD SECTORS
; Address: #2EEA/12010
; Read one or more sectors from disk.
; Input:  HL=start address where disk data will be written;
;         D=start track ID, E=start sector ID;
;         B=number of sectors to be read.
; Output: HL=address of next position after the last written byte;
;         (RWSECID)=logical sector ID after the last read sector;
;         (RWTRKID)=logical track ID where that sector is in.
; Called by: READT0SX, COPYCHUNK, MOVESECT, FILELOAD01, INITSTREAM, RD_CHBUFF. 
;------------------------------------------------------------------------------
RDSECTORS               ;#2EEA
    xor a               ;       A=#00, 'write to disk' flag.
    jr RW_SECTORS       ;#2F11  Jump to the common part for RDSECTORS and
                        ;       WRSECTORS.

;------------------------------------------------------------------------------
; Subroutine: SaVe ENTRY
; Address: #2EED/12013
; Save to disk, a directory entry stored at DOS variable starting from FILENAME.
; Called by: ERASEFILE, DS_MOVE.
;------------------------------------------------------------------------------
SV_ENTRY                ;#2EED
    call PUTENTRY       ;#27BC  Copy directory entry to printer buffer.

;-----------------------------------------------------------------------------
; Subroutine: WRiTe BUFFER
; Address: #2EF0/12016
; Write printer buffer to disk. This subroutine often is called after READ_CS
;or PUTENTRY that increments (RWSECID); owing to this, WRT_BUFFER decrement
;sector ID before writing to disk.
; Input: (RWTRKID)=ID of track to write, (RWSECID)=(ID of sector to write)+1.
; Called by: DIR_RET01, COPYALL, COPYFILE, DS_COPY, DS_ERASE, GETENTRY, 
;PUTENTRY, DS_MOVE, SAVEFILE, SV_SGMT, WR_STMFENT. 
;-----------------------------------------------------------------------------
WRT_BUFFER              ;#2EF0
    ld de,(RWSECID)     ;       D=start track, E=start sector.
    dec de              ;       Decrement sector ID.
    ld b,1              ;       Write 1 sector.
    ld hl,BUFFER        ;       Start address

;-----------------------------------------------------------------------------
; Subroutine: WriTe SECTORS
; Address: #2EFA/12026
; Write multiple sectors to disk.
; Input:  HL=start address of data to be written;
;         D=start track ID, E=start sector ID;
;         B=number of sectors to be written.
; Output: HL=address of next position after the last read byte;
;         (RWSECID)=ID of next sector after the last written one;
;         (RWTRKID)=ID of track where that sector is on.
; Called by: COPYCHUNK, MOVESECT, LOADPARM, SAVEFILE, INITSTREAM, WR_CHBUFF. 
;-----------------------------------------------------------------------------
WRSECTORS               ;#2EFA
    push hl             ;       Stack address.
    push de             ;       Stack track/sector ID.
    call FT_DSKTYPE     ;#3DBA  Fetch data of current disk type.
    bit 7,(hl)          ;       Jump forward if bit 7 of disk type is 0
    jr z,WRSECTORS01    ;#2F0D  or if bit 0 is 0.
    bit 0,(hl)
    jr nz,WRSECTORS01   ;#2F0D 
    ld hl,M_RDONLY      ;#397D  "Read only" error message.
    jp ERROR_RET        ;#2DC2  Jump to error handler.

WRSECTORS01             ;#2F0D
    pop de              ;       Unstack track/sector ID.
    pop hl              ;       Unstack address.

;-----------------------------------------------------------------------------
; WRSECTORS02 (#2F0F/12047)
; Alternate entry point of WRSECTORS.  
; Called by: DS_FORMAT.
;-----------------------------------------------------------------------------
WRSECTORS02             ;#2F0F
    ld a,#FF            ;       A=#FF, 'read from disk' flag.

;-----------------------------------------------------------------------------
; RW_SECTORS (#2F11/12049)
; This part is common for RDSECTORS and WRSECTORS subroutines.
;-----------------------------------------------------------------------------
RW_SECTORS              ;#2F11
    ld (FLAGRW),a       ;       Store flag into DOS system variable.

;-----------------------------------------------------------------------------
; Entry point for LDSVBUFF01 subroutine.
;-----------------------------------------------------------------------------
LDSVBUFF02              ;#2F14
    ld (RWSECID),de     ;       D=start track ID, E=start sector ID.
    push bc             ;       Stack number of sectors.
    push hl             ;       Stack address.
    call CURRTRACK      ;#2EE3  Update FDC track register.
    pop hl              ;       Unstack address
    pop bc              ;       Unstack number of sectors.
    xor a               ;       Finish if there is no remaining sector to
    or b                ;       read/write.
    ret z    

RW_SECTORS01            ;#2F22
    push bc             ;       Stack number of sectors.
    push hl             ;       Stack address
    call SAV_RWADD      ;#3E9F  Save address in the system variable.
    ld a,(RWSECID)      ;       Fetch start sector number.
    call SAV_STARTS     ;#3E9B  Save start sector number.
    ld a,(RWTRKID)      ;       Move head onto start track.
    call TRACK_LA       ;#3E0C  
    ld a,(FLAGRW)       ;       Fetch flag and test its value.
    or a
    push af             ;       Save Z flag onto stack.
    call z,READSECTOR   ;#3EA7  Read 1 sector if flag is zero.
    pop af              ;       Restore Z flag from stack.
    call nz,WRITESECTOR ;#3EA3  Write 1 sector if flag is nonzero.
    pop hl              ;       Unstack address
    ld de,256           ;       Increase pointer in 256 bytes (amount of data 
    add hl,de           ;       in 1 sector).
    push hl             ;       Stack address
    ld a,16             ;       This is max allowed sector number plus 1.
    ld hl,RWSECID       ;       Increment sector number.
    inc (hl)
    cp (hl)             ;       Sector number less than 16 is a legal value, 
    jr nz,RW_SECTORS02  ;#2F54  therefore jump forward.
    ld (hl),0           ;       Otherwise, reset sector number and increment
    ld hl,RWTRKID       ;       track number (i.e., take first sector of next
    inc (hl)            ;       track).

RW_SECTORS02            ;#2F54
    pop hl              ;       Unstack address
    pop bc              ;       Unstack number of sectors.
    djnz RW_SECTORS01   ;#2F22  Repeat R/W operation until all sectores are
    ret                 ;       treated.
  
;-----------------------------------------------------------------------------
; Subroutine: TRUNCate LENgth
; Address: #2F59/12121
; If data does not fit into file size, truncate it.
; Input:  DE=length of data (bytes);
;         A=size of file (number of sectors).
;         C flag=0. 
; Output: A=number of sectors (if data does not fit in file),
;          =MSB of file size (if data fits in file);
;         (CODEARG)=0 if 256*A<DE (data does not fit in file).
; Note: HL register pair is preserved.
; Called by: LOADPARM.
;-----------------------------------------------------------------------------
TRUNCLEN                ;#2F59
    push hl             ;       Stack HL.
    ld h,a              ;       HL=256*(number of sectors), length of data that
    ld l,0              ;       fits in A sectors.
    push hl             ;       Stack calculated length of data.
    sbc hl,de           ;       Reset CODEARG flag if calculated length is
    call c,RESCODARG    ;#2F69  less than length of file.
    pop hl              ;       Unstack calculated length of data.
    ld a,h              ;       A=file size (number of sectors).
    pop hl              ;       Unstack HL.
    ret c               ;       Return if data does not fit file.
    ld a,d              ;       A=MSB of file size.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: RESet CODeARG
; Address: #2F69/12137
; Reset CODEARG system variable. FILELOAD01 will not truncate last sector when
;loading file.
; Output: (CODEARG)=0;
;         C flag=1.
; Called by: TRUNCLEN.
;------------------------------------------------------------------------------
RESCODARG               ;#2F69
    xor a               ;       A=0 but CARRY flag=0.
    ld (CODEARG),a      ;       Assign 0 to (CODEARG).
    scf                 ;       Restore CARRY flag=1.
    ret                 ;       End of subroutine.

;==============================================================================
; DOS Statement: FORMAT 
; Address: #2F6F/12143
; Initialize a disk.
; Syntax: FORMAT <l$> 
; (l$=disk label)
;==============================================================================
DS_FORMAT               ;#2F6F
; Parse argument.
    ld hl,#FFFF         ;       Assign #FF to DOS system variables.
    ld (VAR_A),hl       ;       (VAR_A_H)=#FF, verify after formatting disk.
    ld (VAR_B),hl
    ld (NODISK),hl      ;       (NODISK)=#FF, READTRACK01 will not raise error.
    call NOARG          ;#23AA  Raise syntax error condition if no argument is 
    jp z,ER_SYNTX       ;#2DB3  found in the command line (label is mandatory).
    call GET1ARG_S      ;#2E7C  Get string for disk label.
    call SYN_CHCK       ;#2E0E  Return if DOS is in syntax checking mode.
    call GET_FNAME      ;#2CF2  Change drive if neccessary and store label in 
                        ;       FILENAME system variable.
; Fetch number of tracks.
    call FT_DSKTYPE     ;#3DBA  Fetch data of current disk type.
    and %10000000       ;       Bit 7: 1=80 tracks, 0=40 tracks.
    ld a,40             ;       A=40 tracks.
    jr z,DS_FORMAT01    ;#2F95  Jump if bit 7=0.
    ld a,80             ;       A=80 tracks.

DS_FORMAT01             ;#2F95
;(#2F95/12181)
; Detect number of sides: (VAR_B_H)=#80 for single side disk,
;                                  =#FF for double side disk.
; This is done trying to format first track of each side with differente track
;ID. 
    ld (VAR_A_L),a      ;       Store number of tracks (40 or 80) of the disk.
    call RESTORE        ;#3D3D  Move head to track 0.
    call SELSIDE1       ;#30A3  Select side 1 of disk.
    call LONGDELAY      ;#3E3D  Wait 0.9 s.
    ld e,1              ;       Format first track of side 1 with ID 1.
    call FMT_TRK        ;#30AA 
    call SELSIDE0       ;#3089  Select side 0 of disk.
    ld e,0              ;       Format first track of side 0 with ID 0.
    call FMT_TRK        ;#30AA
    ld a,(FILENAME)     ;       Check if first character of label in the 
    cp "$"              ;       (FILENAME) is "$". Jump forward, skipping disk 
    jr z,DS_FORMAT02    ;#2FC8  detection and forcing single side disk format.
    call SELSIDE1       ;#30A3  Select side 1. 
    call LONGDELAY      ;#3E3D  Wait 0.9 s.
    call READTRACK01    ;#3E52  Read track ID.
    ld a,h              ;       Value other than 1 implies single sided (SS) 
    cp 1                ;       disk; therefore, jump forward to keep 
    jr nz,DS_FORMAT02   ;#2FC8  (VAR_B_H)=#FF.
    ld a,#80            ;       Otherwise, (VAR_B_H)=#80 to signal 
    ld (VAR_B_H),a      ;       'double sided (DS) disk'.

DS_FORMAT02             ;#2FC8
; Format disk physically and prepare new configuration sector.
    call FMTDISK        ;#3164  Format physically all tracks.
    ld hl,BUFFER        ;       Clear printer buffer. This space will be used 
    ld (hl),0           ;       to make a new disk configuration sector.
    ld de,BUFFER+1
    ld bc,255
    ldir
    ld bc,VAR_A_L       ;       BC=address of variable with number of tracks.
    ld de,VAR_B_H       ;       DE=address of variable with SS/DS disk flag.
    ld a,(bc)           ;       Jump forward for 80 track disk.
    cp 80
    jr z,DS_FORMAT05    ;#2FF6 
    ld a,(de)           ;       Jump forward for DS disk.
    cp #80
    jr z,DS_FORMAT03    ;#2FEF 
    ld a,#19            ;       ID for disk with 40 tracks and 1 side.
    ld hl,624           ;       HL=624 free sectors.
    jr DS_FORMAT06      ;#3002  Jump forward.

DS_FORMAT03             ;#2FEF
    ld a,#17            ;       ID for disk with 40 tracks and 2 sides.

DS_FORMAT04             ;#2FF1
    ld hl,1264          ;       HL=1264 free sectors.
    jr DS_FORMAT06      ;#3002  Jump forward. 

DS_FORMAT05             ;#2FF6
    ld a,(de)           ;       Compare flag of number of sides.
    cp #80
    ld a,#18            ;       ID for disk with 80 tracks and 1 side.
    jr nz,DS_FORMAT04   ;#2FF1  Jump backward for SS disk.
    ld a,#16            ;       ID for disk with 80 tracks and 2 sides.
    ld hl,2544          ;       HL=2544 free sectors.

DS_FORMAT06             ;#3002
; New configuration sector is prepared into printer buffer.
    ld (BUFFER+CS_DTYPE),a  ;   Store disk type ID.
    ld (BUFFER+CS_NFREE),hl ;   Store free space value.
    ld a,1                  ;   Store first free track.
    ld (BUFFER+CS_FREET),a
    ld a,16                 ;   Store Beta disk ID (#10/16).
    ld (BUFFER+CS_IDENT),a
    ld hl,BUFFER+234        ;   Fill BUFFER+234 to BUFFER+242 with spaces 
    ld de,BUFFER+235        ;   (" ", #20 or 32).
    ld bc,8
    ld (hl),32
    ldir
    ld hl,FILENAME          ;   Copy label stored at FILENAME.
    ld de,BUFFER+CS_LABEL
    ld bc,8
    ldir
; Printer buffer is written in the disk at sector 8 of track 0.
    call SELSIDE0       ;#3089  Select side 0 of disk.
    ld b,1              ;       Write 1 sector.
    ld de,8             ;       D=track 0, E=sector 8 (configuration sector).
    ld hl,BUFFER        ;       Save printer buffer contents.
    call WRSECTORS02    ;#2F0F  Write configuration sector to disk.
; Print disk label, number of error-free sectors and total number of free 
;sectors.
    ld a,(CODEARG)      ;       Fetch number of verify errors and store onto
    push af             ;       stack.
    xor a    
    ld (FILETYPE),a     ;       Set end of string marker after FILENAME.
    ld hl,(BUFFER+CS_NFREE) ;   Fetch number of free sectors and store 
    ld (VAR_A),hl       ;       temporarily into VAR_A.
    ld hl,FILENAME      ;       HL=address of disk label string.
    rst 24              ;       Print disk label.
    ld a,13             ;       Print 'Enter' (new line).
    rst 16
    ld hl,(VAR_A)       ;       Fetch number of free sectors.
    pop af              ;       Unstack number of verify errors.
    push hl             ;       Stack number of free sectors.
    ld d,0              ;       DE=number of verify errors.
    ld e,a
    sbc hl,de
    ld b,h              ;       Number of available sectors: BC=HL-DE.    
    ld c,l    
    call BAS_PRNTBC     ;#2E45  Print value of BC.
    ld a,"/"            ;       Print 'slash' character.
    rst 16    
    pop bc              ;       Unstack number of free sectors.
    call BAS_PRNTBC     ;#2E45  Print this value.
    jp DSTM_RET         ;#2170  Return to DOS interpreter.

;------------------------------------------------------------------------------
; Sector interleaving table (#3066/12390).
; Sectors in a track are recorded in non-sequencial order given by this table.
;There are always one sector between two sectors with contiguous ID, thus 
;------------------------------------------------------------------------------
T_INTLV
    defb 1,9,2,10
    defb 3,11,4,12
    defb 5,13,6,14
    defb 7,15,8,16
    defb 1

;------------------------------------------------------------------------------
; Subroutine: SCAN Number of  TRacKs
; Address: #3077/12407
; Measure number of tracks of disk (40 or 80).
; Output: A=number of tracks;
;         (VAR_A_L)=number of tracks.
; Called by: SEL_DRIVE.
;------------------------------------------------------------------------------
SCAN_NTRK               ;#3077
    call FT_STEPRT      ;#3DB1  A=stepping motor rate.
    or %00010001        ;       Set bit 0 (increment rate) and bit 4 (make code 
    ld b,a              ;       for FDC command 'SEEK').
    ld a,50             ;       Send 'SEEK 50' command to FDC (exceed last 
    call SEEK_A         ;#3DED  track for 40 track disk).
    ld a,2              ;       Send 'SEEK 2' command to FDC (do backwards 
    call SEEK_A         ;#3DED  motion and stop before track 0).
    call DELAY          ;#3DA6  Wait 0.15 s.
    in a,(31)           ;       Read FDC status register and mask out all bits 
    and %00000100       ;       except bit 2 (TRACK00). This bit is 1 if head
                        ;       is on track 0 of disk.
    ld a,80             ;       Number of tracks is 80 if head is not on track
    jr z,SCAN_TRKN01    ;#3094  0 (it is supposed to be on track 2).
    ld a,40             ;       Otherwise, number of tracks is 40.

SCAN_TRKN01             ;#3094
    ld (VAR_A_L),a      ;       Store number of tracks in the system variable.
    ret    

;------------------------------------------------------------------------------
; Subroutine: SELect SIDE 0 
; Address: #3098/12440
; Select side 0 of disk.
; Called by: DS_FORMAT, DS_FORMAT, FMTDISK, TRACK_LA, READTRACK.
;------------------------------------------------------------------------------
SELSIDE0                ;#3089
    ld a,(PORT255)      ;       Take last byte sent do port 255 and rise bit 4 
    or %00111100        ;       to select side 0.

SELSD_OUT               ;#309D
    ld (PORT255),a      ;       Update PORT255 system variable and send byte 
    out (255),a         ;       to the port.
    ret                 ;       End of subroutine.
;------------------------------------------------------------------------------
; Subroutine: SELect SIDE 1
; Address: #30A3/12451
; Select side 1 of disk.
; Called by: DS_FORMAT, FMTDISK, PHYSTRACK.
;------------------------------------------------------------------------------
SELSIDE1                ;#30A3
    ld a,(PORT255)      ;       Take last byte sent do port 255 and lower bit 4 
    and %01101111       ;       to select side 1.
    jr SELSD_OUT        ;#309D  Jump backward to send byte to port 255.

;------------------------------------------------------------------------------
; Subroutine: ForMaT TRacK
; Address: #30AA/12458
; Format one track of disk. WRITE TRACK is executed by FDC and necessary data
;must be fed by the computer. The track ID field is filled with number held by
;E register but no attempt is made to check the real drive head position.
; Input:  E=track number;
;         (VAR_A_H)=0 (verify disk after formatting).
; Called by: FMTDISK, DS_FORMAT.
;------------------------------------------------------------------------------
FMT_TRK                 ;#30AA
    ld a,#F4            ;       Send WRITE TRACK command to FDC.
    out (31),a
    ld hl,T_INTLV       ;       HL=address of sector interleave table.
    ld c,127            ;       C=address of port for FDC data register.

FMT_TRK01               ;#30B3
    ld b,10             ;       Send #4E to data register 10 times.
    ld d,#4E
    call PUTDATA01      ;#3158 
    ld b,12             ;       Send #00 to data register 12 times.
    ld d,#00
    call PUTDATA01      ;#3158 
    ld b,3              ;       Send #F5 to data register 3 times.
    ld d,#F5
    call PUTDATA01      ;#3158 
    ld d,#FE            ;       Send #FE to data register (ID address mark).
    call PUTDATA        ;#3156 
    ld d,e              ;       Send track number to data register.
    call PUTDATA        ;#3156 
    ld d,#00            ;       Send #00 to data register (side number).
    call PUTDATA        ;#3156 
    ld d,(hl)           ;       Get data from T_INTLV table (sector number) and 
    call PUTDATA        ;#3156  send to data register.
    ld d,#01            ;       Send #01 to data register.
    call PUTDATA        ;#3156 
    ld d,#F7            ;       Send #F7 to data register (2 CRCs written).
    call PUTDATA        ;#3156 
    ld b,22             ;       Send #4E to data register 22 times.
    ld d,#4E
    call PUTDATA01      ;#3158 
    ld b,12             ;       Send #00 to data register 12 times.
    ld d,#00
    call PUTDATA01      ;#3158 
    ld b,3              ;       Send #F5 to data register 3 times.
    ld d,#F5
    call PUTDATA01      ;#3158 
    ld d,#FB            ;       Send #FB to data register (data address mark).
    call PUTDATA        ;#3156 
    ld b,0              ;       Send #00 to data register 256 times (data).
    ld d,#00
    call PUTDATA01      ;#3158 
    ld d,#F7            ;       Send #F7 to data register (2 CRCs written).
    call PUTDATA        ;#3156 
    ld b,50             ;       Send #4E to data register 50 times.
    ld d,#4E
    call PUTDATA01      ;#3158 
    ld a,(hl)           ;       Update pointer for T_INTLV table to the next 
    inc hl              ;       sector value.
    cp 16               ;       Jump backward and repeat until sector number 
    jr nz,FMT_TRK01     ;#30B3  is 16.
    ld b,#00            ;       Send #4E to data register 256 times.
    call PUTDATA01      ;#3158 
    jp m,FMT_TRK02      ;#3122  Jump forward if INTRQ=1, otherwise send #4E
    call PUTDATA01      ;#3158  to data register 50 times.

FMT_TRK02               ;#3122
    in a,(31)           ;       Jump to write protected disk error handler if 
    and %01000000       ;       bit 6 (PROTECTED) of FDC status register is 1.
    jp nz,RDWRSECT03    ;#3ED0 
    ld a,(VAR_A_H)      ;       Exit if (VAR_A_H) is not 0, skippping format
    or a                ;       verify.
    ret nz    
    ld a,e              ;       Take track number from E and send to FDC track
    out (63),a          ;       register.
    ld hl,T_INTLV+1     ;       HL =address of the second element of sector 
                        ;       interleaving table.
FMT_TRK03               ;#3134
    ld b,3              ;       Number of attempts if any error.
    ld a,(hl)           ;       Get sector number from table and send to FDC 
    out (95),a          ;       sector register.
    push hl             ;       Stack address of interleave table element.

FMT_TRK04               ;#313A
    ld a,#80            ;       Send READ SECTOR command to FDC.
    out (31),a
    push bc             ;       Stack counter.
    call FDC_RDATA02    ;#3F7B  Read data from FDC but discard them (actually,
                        ;       data are written in the ROM). 
    in a,(31)           ;       Read FDC status register.
    or a
    pop bc              ;       Unstack counter.
    jr z,FMT_TRK05      ;#314E  Jump forward if status=0 (no error). Otherwise,
    djnz FMT_TRK04      ;#313A  jump backward to retry (max 3 times).
    ld hl,CODEARG       ;       Increment number of verify errors.
    inc (hl)    

FMT_TRK05               ;#314E
    pop hl              ;       Unstack address of interleave table element.
    ld a,(hl)           ;       Fetch sector number from interleave table.
    inc hl              ;       Increment pointer of table to next position.
    cp 16               ;       Repeat until last sector number is found (16).
    jr nz,FMT_TRK03     ;#3134 
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: PUT DATA
; Address: #3156/12630
; Send one byte of data to FDC data register.
; Input: D=data to send;
;        C=127 (FDC data register port address).
; Called by: FMT_TRK. 
;------------------------------------------------------------------------------
PUTDATA                 ;#3156
    ld b,1              ;       B=1 byte will be sent.
;------------------------------------------------------------------------------
; Subroutine: PUT DATA 01 
; Address: #3158/12632
; Send data to FDC data register.
; Input: D=data to send;
;        C=127 (FDC data register port address);
;        B=number of bytes of data.
; Called by: FMT_TRK.
;------------------------------------------------------------------------------
PUTDATA01               ;#3158
    in a,(255)          ;       Wait for bit 6 (DREQ) or bit 7 (INTRQ) 
    and %11000000       ;       becoming 1.
    jr z,PUTDATA01      ;#3158 
    ret m               ;       Return if INTRQ=1 (command finished).
    out (c),d           ;       Send data to FDC data register port.
    djnz PUTDATA01      ;#3158  Repeat until all bytes are sent.
    ret                 ;       End of subroutine.
  
;------------------------------------------------------------------------------
; Subroutine: ForMaT DISK
; Address: #3164/12644
; Format a disk physically.
; Input: (VAR_A_L)=number of tracks to format;
;        (VAR_B_H)=#80 (format only side 0).
; Called by: DS_FORMAT.
;------------------------------------------------------------------------------
FMTDISK                 ;#3164
    ld hl,VAR_A_L       ;       Fetch number of tracks of disk and initialize 
    ld b,(hl)           ;       counter.
    xor a               ;       A=0.
    inc hl              ;       HL=VAR_A_H 
    ld (hl),a           ;       (VAR_A_H)=0 (verify disk after formatting).
    ld e,#FF            ;       E=track number -1.

FMTDISK01               ;#316D
    push bc             ;       Save track counter.
    inc e               ;       Increment track number.
    ld a,e    
    ld b,#1B            ;       Define slowest stepping motor rate (%11).
    call SEEK_A         ;#3DED  Move disk head onto required track.
    call SELSIDE0       ;#3089  Select side 0 of disk.
    call FMT_TRK        ;#30AA  Format track.
    ld a,(VAR_B_H)
    cp #80
    jr nz,FMTDISK02     ;#3188  Jump forward if (VAR_B_H) flag is #80.
    call SELSIDE1       ;#30A3  Select side 1.
    call FMT_TRK        ;#30AA  Format track of side 1.

FMTDISK02               ;#3188
    pop bc              ;       Restore track counter.
    djnz FMTDISK01      ;#316D  Repeat until all tracks are formated.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: InterFace 1 Variables Swap
; Address: #318C/12684
; ZX Interface 1 'shadow' ROM creates its own extended BASIC system variables 
;starting at #5CB6/23734 and ending at #5CEF/23791. Part of this area overlaps 
;with Beta DOS system variables. To avoid conflicts, the INITVARS subroutine 
;pushes up extended BASIC variables 112 bytes forward. IF1VSWP subroutine swaps
;memory contents at 23747-23791 (BAUD-COPIES of extended BASIC or CHANDATA-
;FILETEMP of DOS) and at 23859-23903 (112 bytes forward). Thus, system 
;variables are toggled among DOS set and extended BASIC set.
; Called by: EXEC_BAS, DSTM_RET, DOS_CLI03, DS_RETURN, CH_OUT01, ER_ENDFILE, 
;CH_INP01, SAVECFGS, LOADCFGS. 
; Note: AF register pair is preserved.
;------------------------------------------------------------------------------
IF1VSWP                 ;#318C
    push af             ;       Stack AF contents.
    ld a,(CHANSCOPY)    ;       First byte of CHANSCOPY is #F4 (LSB of PRINT-
    cp #F4              ;       OUT routine) unless Interface 1 is present.
    jr z,IF1VSWP02      ;#31AD  Skip subroutine if interface is absent.
    ld hl,IF1VAR        ;       When invoked by the first time, (IF1VAR) is 0;
    or (hl)             ;       this subroutine will be skipped, but (IF1VAR) 
    ld (hl),#FF         ;       is toggled so IF1VSWP will run next time. 
    jr z,IF1VSWP02      ;#31AD 
    ld hl,CHANSCOPY+13  ;       Swap DOS and IF1 system variables, separated by 
    ld de,CHANSCOPY+125 ;       112 bytes. The saved IF1 variables start from 
                        ;       BAUD and end at COPIES (23747-23791).
    ld b,45             ;       There are 45 bytes to be swapped.

IF1VSWP01               ;#31A4
    ld c,(hl)           ;       Swap bytes of (HL) and (DE).
    ld a,(de)    
    ld (hl),a    
    ld a,c    
    ld (de),a    
    inc hl              ;       Increment both pointers.
    inc de    
    djnz IF1VSWP01      ;#31A4  Repeat until 45 bytes are swapped.

IF1VSWP02               ;#31AD
    pop af              ;       Unstack AF contents.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: CLEAR LINE
; Address: #31AF/12719
; Clear line editor area.
; Called by: EDITLINE.
;------------------------------------------------------------------------------
CLEARLINE               ;#31AF
    ld hl,(E_LINE)      ;       HL is pointer for line editor area.
    ld (hl),#0D         ;       Put end of line marker (Enter).
    ld (K_CUR),hl       ;       Set current cursor address.
    inc hl              ;       Put end of line editor marker (#80) at next 
    ld (hl),#80         ;       position.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: LOAD LINE
; Address: #31BB/12731
; Load content of line editor memory saved temporarily in ELINE_T.
; Called by: EDITLINE.
;------------------------------------------------------------------------------
LOADLINE                ;#31BB
    ld de,(E_LINE)      ;       Destination is line editor area.
    ld hl,ELINE_T       ;       Origin is this system variable.
    call COPY3B         ;#2242  Copy 3 bytes.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: EDIT LINE
; Address: #31C6/12742
; Edit a line. Command line editor area is cleared if no error has been 
;reported by DOS interpreter. Any error does previous command line contents to
;be copied for further editing. Prompt 'A>', 'B>', 'C>' or 'D>' is shown in the 
;lower lines of screen.
; Called by: DOS_CLI03.
;------------------------------------------------------------------------------
EDITLINE                ;#31C6
    ld a,(D_ERRCOD)     ;       Fetch DOS error code and check if it is equal
    or a                ;       to 0 (no error).
    push af             ;       Stack Z flag.
    call nz,LOADLINE    ;#31BB  Load saved content of line editor if any error.
    pop af              ;       Unstack Z flag.
    call z,CLEARLINE    ;#31AF  Clear line editor area if no error.
    ld hl,(E_LINE)      ;       HL=address of line editor memory.
    call PRT_ENTER      ;#3D1F  Print 'Enter'.
    ld a,(DEFLTDRV)     ;       Fetch default drive number (0-3).
    add a,"A"           ;       Add "A" to get drive letter ("A"-"D").
    rst 16              ;       Print drive letter.
    ld a,">"            ;       Print ">" prompt separator.
    rst 16    
    ld hl,ERR_NR        ;       Set error number to #FF ('0 - OK', there is no
    ld (hl),#FF         ;       error yet).
    jp BAS_EDITOR       ;#2E2B  Jump to EDITOR subroutine of BASIC ROM.

;------------------------------------------------------------------------------
; Subroutine: RND ARGument
; Address: #31E9/12777
; Fetch numeric argument for random access stream file. 
; Output: (VAR_A)=(record length)+1
; Called by: DS_OPEN.
;------------------------------------------------------------------------------
RND_ARG                 ;#31E9
    call BAS_NXTCHR     ;#2ECB  Seek next printable character.
    call BAS_GETCHR     ;#2E26  Get character.
    cp ","              ;       Raise syntax error if character is not comma.
    jp nz,ER_SYNTX      ;#2DB3 
    ld hl,(VAR_C)       ;       Save temporarily value of (VAR_C) (stream 
    ld (VAR_B),hl       ;       number) into (VAR_B).
    call GETARG_I       ;#2EA8  Evaluate argument (record length) and put in 
                        ;       (VAR_C).
    call SYN_CHCK       ;#2E0E  Return if DOS is in syntax checking mode.
    ld hl,(VAR_C)       ;       Fetch record length.
    ld a,h              ;       Fetch MSB of record length.
    or a                ;       Raise syntax error condition if MSB of record 
    jp nz,ER_SYNTX      ;#2DB3  length is not 0 (i.e. length>255).
    inc hl              ;       Increment record lenght (range is now 1-256) 
    ld (VAR_A),hl       ;       and store into (VAR_A).
    ld hl,(VAR_B)       ;       Restore value of (VAR_C) (stream number).
    ld (VAR_C),hl
    ret                 ;       End of subroutine.

;==============================================================================
; DOS Statement: OPEN 
; Address: #3213/12819
; Open a file and associate it with a stream.
; Syntax: OPEN #<s>,<n$>W                  (open sequencial file in write mode)
;         OPEN #<s>,<n$>R                   (open sequencial file in read mode)
;         OPEN #<s>,<n$>RND,<reclen>                  (open random access file)
; (s=stream number, 4-15; n$=filename; reclen=length of record)
;==============================================================================
DS_OPEN                 ;#3213
; Evaluate command line to find stream number and filename.
    ld hl,(DSTMADDR)    ;       DOS interpreter cursor is placed at start of
    ld (CH_ADD),hl      ;       command line.
    call GETARG_I       ;#2EA8  Evaluate numeric argument (stream number) and 
                        ;       put in (VAR_C).
    call GETARG_CS      ;#2E6D  Evaluate string argument (filename) after a
                        ;       comma.
DS_OPEN01               ;#321F
; This loop scan command line to find a letter or BASIC token.
    call BAS_GETCHR     ;#2E26  Evaluate a character from command line.
    cp "A"              ;       Jump forward if character is "A" or greater.
    jr nc,DS_OPEN02     ;#322B
    call BAS_NXTCHR     ;#2ECB  Otherwise, advance cursor to next character and
    jr DS_OPEN01        ;#321F  make new attempt.

DS_OPEN02               ;#322B
; Check these possible arguments: 'RND', "R" or "W"; any other value raises 
;error condition.
    cp #A5              ;       Check if character is 'RND' token.
    push af             ;       Stack Z flag.
    call z,RND_ARG      ;#31E9  Check syntax for random mode file and fetch 
                        ;       arguments.
    pop af              ;       Unstack Z flag.
    jr z,DS_OPEN03      ;#323F  Jump forward if 'RND' token was found.
    and %11011111       ;       Change character to uppercase letter.
    cp "R"              ;       Jump forward if it is "R".
    jr z,DS_OPEN03      ;#323F
    cp "W"              ;       Raise syntax error condition if character is
    jp nz,ER_SYNTX      ;#2DB3  not "W".

DS_OPEN03               ;#323F
    ld (OPENMODE),a     ;       Store mode of opened file.
    call SYN_CHCK       ;#2E0E  Return if DOS is in syntax checking mode.
    ld a,"#"            ;       File type is "#".
    ld (FILETYPE),a
    ld a,0              ;       Initialize segment number with 0.
    ld (FILEPARM1),a
    call SEEKSTRM       ;#326C  Seek stream file in the directory.
    push af             ;       Stack Z flag (file found or not) and A.
    call VRF_STRM       ;#32A0  Verify if stream is already open or available.
    pop af              ;       Unstack Z flag and A.
    push af             ;       Stack Z flag and A.
    call nz,NEWSTRM     ;#331C  Save new stream file if it was not found.
    pop af              ;       Unstack Z flag and A.
    call INITSTREAM     ;#32D6  Initialize the new stream.
    ld hl,(DSTMADDR)    ;       All BASIC area has been moved forward 292  
    ld bc,292           ;       bytes, therefore DOS interpreter cursor has to
    add hl,bc           ;       be pushed too.
    ld (DSTMADDR),hl
    jp DSTM_RET         ;#2170  Return to DOS interpreter.

;------------------------------------------------------------------------------
; Subroutine: SEEK STReaM
; Address: #326C/12098
; Seek stream file in the directory. For 'Read' mode, fetch entry info of the
;first segment. For 'Write' or 'Random' mode, fetch entry info of the last 
;segment.
; Output: Z flag=1 (file was found and entry info was copied),
;               =0 (file was not found);
;         A=0 if file was found.
; Called by: DS_OPEN.
;------------------------------------------------------------------------------
SEEKSTRM                ;#326C
    ld a,10             ;       When seeking for a file, 10 bytes of data must
    ld (CMP_SIZE),a     ;       match in the comparison.
    call SEEKFILE       ;#2D49  Seek file in the directory.
    push af             ;       Stack Z flag.
    call ID_TYPE        ;#2384  Read configuration sector from disk.
    pop af              ;       Unstack Z flag.
    jr nz,SEEKSTRM03    ;#3297  Jump forward if file not found.
    ld a,(OPENMODE)     ;       Fetch opened stream mode.
    cp "R"              ;       Jump forward if stream mode is 'Read'.
    jr z,SEEKSTRM02     ;#3292

SEEKSTRM01              ;#3282
; "W" or "RND" file was found. Seek for the last segment file of stream.
    ld hl,FILEPARM1     ;       HL=FILEPARM2 (segment number).
    inc (hl)            ;       Increment segment number and seek file in the
    call SEEKFILE01     ;#2D4C  directory.
    jr z,SEEKSTRM01     ;#3282  Retry until file is not found.
    ld hl,FILEPARM1     ;       Decrement segment number to find the last 
    dec (hl)            ;       stream file  already existent in the directory.
    call SEEKFILE01     ;#2D4C  Seek that file.

SEEKSTRM02              ;#3292
; Get entry of first segment for "R" mode and last segment for "W" or "RND" 
;mode.
    call GETENTRY       ;#27AE  Get entry info into DOS system variables.
    xor a               ;       A=0 and Z flag=1.
    ret                 ;       End of subroutine.

SEEKSTRM03              ;#3297
; File was not found.
    ld a,(OPENMODE)     ;       Return if stream file mode is not "R" (read).
    cp "R"              ;       Otherwise, raise 'no file' error condition
    ret nz              ;       because there is nothing to read.
    jp ER_NOFILE        ;#2358 

;------------------------------------------------------------------------------
; Subroutine: VeRiFy STReaM
; Address: #32A0/12960
; Check if stream is available for opening. Raise error condition if stream is
;already opened.
; Input:  (VAR_C_L)=stream number (4-15). 
; Output: A=0 if stream is closed and available.
;         C flag=0 (used by INITSTREAM).
; Called by: DS_OPEN, INITSTREAM.
;------------------------------------------------------------------------------
VRF_STRM                ;#32A0
    ld a,(VAR_C_L)      ;       Fetch stream number.
    ld hl,#1727         ;       Call STR-DATA1 (#1727/5627) routine of BASIC 
    call CALLBAS        ;#2E36  ROM to get stream data.
    ld a,b              ;       Closed stream returns BC=0.
    or c                ;       Flags: C=0, Z=1 (if BC=0).
    jp nz,ER_STMOPEN    ;#32AF  Raise 'stream opened' error condition if stream
                        ;       is already opened.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Error routine: STreaM OPENed
; Address: #32AF/12975
; Error arising from attempt to open an already opened stream.
; Called by: VRF_STRM.
;------------------------------------------------------------------------------
ER_STMOPEN              ;#32AF
    ld a,25             ;       Assign error number 25 (Q - Parameter error).
    ld (ERR_NR),a
    ld hl,M_STMOPEN     ;#37D7  Message: "Stream opened".
    ld a,10             ;       DOS error code 10.

ER_NDFILE01             ;#32B9
    jp DSTM_ERRET       ;#2CE5  Jump to error handler.

;------------------------------------------------------------------------------
; Error routine: No Disk FILE
; Address: #32BC/12988
; There was an attempt to close a stream not associated with stream file (type
;"#") channel.
; Called by: DS_CLOSE.
;------------------------------------------------------------------------------
ER_NDFILE               ;#32BC
    ld a,11             ;       DOS error code 11.
    ld hl,M_NODFILE     ;#37E5  Message: "Not disk file".
    jr ER_NDFILE01      ;#32B9  Jump backward to error handler.

;------------------------------------------------------------------------------
; Subroutine: INIT RND
; Address: #32C3/12995
; Initialize channel information fields related to random access mode file.
; Called by: INITSTREAM.
; Output: A=#7F/127.
; Note: HL register pair is preserved.
;------------------------------------------------------------------------------
INIT_RND                ;#32C3
    push hl             ;       Stack HL value.
    ld c,32             ;       HL=address of CH_RLEN filed of channel 
    rst 40              ;       information block (offset=+32).
    ld a,(VAR_A_L)      ;       Store record length into (CH_RLEN).
    ld (hl),a    
    inc hl
    xor a               ;       Reset 'CH_WCUR' field of channel info block 
    ld (hl),a           ;       (offset=+33), workspace and record are empty.
    inc hl              ;       Reset 'CH_WREC' field of channel info block
    ld (hl),a           ;       (offset=+34), output is waiting for record ID.
    inc hl              ;       Reset 'CH_FLSH' field of channel info (offset=
    ld (hl),a           ;       +35), channel info will not be written to disk.
    ld a,#7F            ;       #7F=mode "RND".
    pop hl              ;       Unstack HL value.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: INIT STREAM
; Address: #32D6/13014
; Initialize a new stream.
; Called by: DS_OPEN.
;------------------------------------------------------------------------------
INITSTREAM              ;#32D6
    push af             ;       Stack A (A=0 if file was found; see DS_OPEN).
    call VRF_STRM       ;#32A0  Check if stream is already open.
    ex de,hl            ;       Save stream data address into DE.
    ld hl,(PROG)        ;       Start address of BASIC area, new channel will
                        ;       be created here.
    ld bc,(CHANS)       ;       Calculate displacement from start of channel
    sbc hl,bc           ;       info area. Note: C flag=0 owing to VRF_STRM.
    ex de,hl
    ld (hl),e           ;       Store displacement value into stream data area.
    inc hl              ;       Thus, new channel is assigned to the stream
    ld (hl),d    
    call MKNEWCHAN      ;#3346  Make new channel (HL=CH_MODE field address).
    ld a,(OPENMODE)     ;       Fetch mode of opened stream file and compare
    cp #A5              ;       with 'RND' token.
    call z,INIT_RND     ;#32C3  Call subroutine if mode is 'RND' and jump
    jr z,INITSTREAM01   ;#32FF  forward to skip further checking.
    ld a,(OPENMODE)     ;       Check if "R" mode.
    cp "R"
    ld a,#FF            ;       #FF=mode "W".
    jr nz,INITSTREAM01  ;#32FF  Jump forward if mode is not "R".
    xor a               ;       #00=mode "R".

INITSTREAM01            ;#32FF
    ld (hl),a           ;       CH_MODE=#00 ("R")/#7F ("RND")/#FF ("W").
    pop af              ;       Unstack A (A=0 if file was found; see DS_OPEN).
    jp INITSTREAM02     ;#3304  ??????

INITSTREAM02            ;#3304
    push af             ;       Stack A (A=0 if file was found; see DS_OPEN).
    ld bc,20            ;       HL=address of 'CH_FLSH' field of channel 
    add hl,bc           ;       information block (offset=+35).
    push hl             ;       Stack HL.
    call CURSSECT       ;#34B4  DE=track/sector ID of current cursor position.
    pop hl              ;       Unstack HL.
    inc hl              ;       HL points to offset=+36 (start of channel 
                        ;       buffer)
    ld b,1              ;       1 sector (256 bytes) to be transferred.
    pop af              ;       Unstack A (A=0 if file was found; see DS_OPEN).
    or a                ;       Check if A=0.
    push af             ;       Stack Z flag.
    call nz,WRSECTORS   ;#2EFA  Write last sector if file hadn't been found and 
                        ;       a new one was created. Data is read from 
                        ;       channel buffer.
    pop af              ;       Unstack Z flag.
    call z,RDSECTORS    ;#2EEA  Read last sector if file was found. Data is
                        ;       written into channel buffer.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: NEW STReaM
; Address: #331C/13084
; Save a new stream file. This file will be the first segment (0) and its size
;will be 4096 bytes.
; Called by: DS_OPEN.
;------------------------------------------------------------------------------
NEWSTRM                 ;#331C
    ld hl,(VAR_A)       ;       Save (VAR_A) onto stack.
    push hl    
    ld hl,8192          ;       Parameter 1 of file to save: (VAR_A_L)=0, first
    ld (VAR_A),hl       ;       segment; (VAR_A_H)=#20/32.
    call SV_SGMT        ;#332E  Save first segment of stream file.
    pop hl    
    ld (VAR_A),hl       ;       Restore (VAR_A) from stack.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: SaVe SeGMenT
; Address: #332E/13102
; Save a segment of a stream file with size of 4096 bytes/16 sectors. The file
;parameter 2 of directory entry (length of data) is 0.
; Input: (VAR_A_L)=segment of stream file (LSB of parameter 1);
;        (VAR_A_H)=#20/32 (MSB of parameter 1).
; Called by: NEWSTRM, NEWSEGMT.
; Note: file body is filled with DOS ROM contents starting from the address 
;pointed by fileparm 1 (8192+segment ID).
;------------------------------------------------------------------------------
SV_SGMT                 ;#332E
    ld hl,4096          ;       File length is 4096 bytes.
    ld (VAR_B),hl
    call DIRFULL        ;#2B6E  Check if directory if full.
    call SAVEFILE       ;#2C03  Save file.
    ld hl,0             ;       Reset parameter 2 of directory entry (length of
    ld (FILEPARM2),hl   ;       data).
    call PUTENTRY       ;#27BC  Write directory entry to disk.
    jp WRT_BUFFER       ;#2EF0  Jump to routine that writes printer buffer to
                        ;       disk.

;------------------------------------------------------------------------------
; Subroutine: MaKe NEW CHAN
; Address: #3346/13126
; Make channel "D" for stream file operations. New channel information block 
;starts at the end of channel information area.
; Output: HL=(channel information block address)+15
; Called by: INITSTREAM.
;------------------------------------------------------------------------------
MKNEWCHAN               ;#3346
    ld hl,(PROG)        ;       New channel information block will be placed 
    dec hl              ;       just before BASIC program area.
    ld (CURCHL),hl      ;       Assign current channel address.
    push hl             ;       Stack channel start address.
    ld bc,292           ;       Open space of 292 bytes there (DE=address of
    call BAS_MKROOM     ;#2EDD  last byte of new space).
    ld a,0              ;       Memory will be filled with 0.
    ld b,0              ;       Counter for 256 bytes.

MKNEWCHAN01             ;#3358
; Clear channel buffer (CH_BUFF).
    ld (de),a           ;       Fill last 256 bytes (offset +36 to +291 with 0, 
    dec de              ;       clearing the new channel buffer (CH_BUFF).
    djnz MKNEWCHAN01    ;#3358
    pop hl              ;       Unstack channel start address.
; Initialize each field of channel information block.
    push hl             ;       Stack channel start address.
    ld de,CH_OUTPUT     ;#3C0F  Channel output routine address.
    ld (hl),e           ;       Offset +0 (CH_OUTR): output routine address.  
    inc hl    
    ld (hl),d    
    inc hl    
    ld de,CH_INPUT      ;#3C09  Channel input routine address.
    ld (hl),e           ;       Offset +2 (CH_INPR): input routine address.
    inc hl    
    ld (hl),d    
    inc hl    
    ld (hl),"D"         ;       Offset +4 (CH_NAME): channel name "D".
    inc hl              ;       Offset +5 (CH_IF1O): skipped and not used.
    inc hl    
    inc hl              ;       Offset +7 (CH_IF1I): skipped and not used.
    inc hl    
    inc hl              ;       Offset +9 (CH_BLEN): length of channel info
    ld (hl),#24         ;            block (#0124/292 bytes).
    inc hl    
    ld (hl),#01
    inc hl              ;       Offset +11 (CH_DRIV): drive with stream file.
    ld a,(CURRDRIVE)    ;       Use value of current drive.
    ld (hl),a    
    inc hl              ;       Offset +12 (CH_ENTR): file entry position.
    ld a,(FILEPOS)      ;       Use value of current file. 
    ld (hl),a    
    inc hl              ;       Offset +13 (CH_DCUR): cursor position, 0 for 
    ld a,(OPENMODE)     ;            'R' mode, end of file for another modes.
    cp "R"
    ld (hl),0           ;       
    jr z,MKNEWCHAN02    ;#3390  Jump forward if 'R' mode, otherwise fetch LSB
    ld a,(FILEPARM2)    ;       of file length (FILEPARM2) and put into 
    ld (hl),a           ;       (CH_DCUR).

MKNEWCHAN02             ;#3390
    inc hl              ;       Move pointer to CH_DCUR+1.
    ld (hl),b           ;       (HL)=0 (B=0 owing to last DJNZ).
    jr z,MKNEWCHAN03    ;#3398  Jump forward if 'R' mode.
    ld a,(FILEPARM2+1)  ;       Otherwise, (CH_DCUR+1)=MSB of file length.
    ld (hl),a

MKNEWCHAN03             ;#3398
    inc hl              ;       Offset +15 (CH_MODE).
    ex de,hl            ;       DE=CH_MODE.
    pop hl              ;       Unstack channel start address.
    push de             ;       Stack CH_MODE.
    ld de,16            ;       Offset +16 (CH_FNAM).
    add hl,de           ;       HL=CH_FNAM.
    ex de,hl            ;       Source address=CH_FNAM.
    ld hl,FILENAME      ;       Start address of directory entry.
    ld bc,16            ;       Length of entry.
    ldir                ;       Copy directory entry to (CH_FNAM).
    pop hl              ;       Unstack CH_MODE.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: CHannel BUFFer ADDress
; Address: #33AB/13227
; Return channel buffer address at current cursor position.
; Output: HL=address of current cursor position.
; Called by: CH_OUT01, CH_INP01.
;------------------------------------------------------------------------------
CHBUFFADD               ;#33AB
    ld c,13             ;       HL=address of 'CH_DCUR' field of channel
    rst 40              ;       channel information block (offset=+13).
    ld c,(hl)           ;       Take LSB of cursor position as offset value to
    rst 40              ;       calculate address of pointer.
    ld bc,36            ;       Add 36 to place pointer into channe buffer.
    add hl,bc    
    ret                 ;       End of subroutine.
 
;------------------------------------------------------------------------------
; Subroutine: CHANnel BUFFer
; Address: #33B5/13237
; Return start address of channel buffer.
; Output: HL=start address of channel buffer.
; Called by: WR_CHBUFF, RD_CHBUFF.
;------------------------------------------------------------------------------
CHANBUFF                ;#33B5
    ld c,36             ;       Offset=+36, CH_BUFF.

;------------------------------------------------------------------------------
; Subroutine: SELect CHannel INFO
; Address: #33B7/13239
; Main routine of RST 40/#28.
; Input:  C=displacement value.
; Output: HL=address of current channel with displacement added.
; Called by: INIT_RND, CHBUFFADD, CH_OUT02, GETSEGMT, NEWSEGMT, INPNXTCHR, 
;SEEKNXTSEG, RD_STMFENT, WR_CHBUFF, CURSSECT, STREAMDRV, ENDSTMFL, CHOUT_RND,
;GETRECORD, RNDRECORD, FLUSHCBUF, READMODE, WR_STMFENT.
;------------------------------------------------------------------------------
SEL_CHINFO              ;#33B7
    ld b,0              ;       MSB of BC register pair is 0.
    ld hl,(CURCHL)      ;       Fetch current channel info address.
    add hl,bc           ;       Add displacement.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; CH_OUT02 (#33BE/13246)
; Part of CH_OUT routine, continuation of CH_OUT01 (#34DB/13531).
;------------------------------------------------------------------------------
CH_OUT02                ;#33BE
    ld c,13             ;       HL=address of 'CH_DCUR' field of channel
    rst 40              ;       information block (offset=+13).
    inc (hl)            ;       Move cursor to the next position.
    ret nz              ;       Return if channel buffer is not exceeded.
    push hl             ;       Stack HL pointer.
    call STREAMDRV      ;#34D4  Select drive with stream file.
    call WR_CHBUFF      ;#348D  Write channel buffer into stream file.
    pop hl              ;       Unstack HL pointer.
    inc hl              ;       Advance pointer to MSB of cursor position.
    inc (hl)            ;       Increment MSB of cursor position.
    push hl             ;       Stack HL pointer.
    call RD_CHBUFF      ;#34A9  Fill channel buffer with current sector.
    pop hl              ;       Unstack HL pointer.
    ld a,16             ;       Check if file reached 4096 bytes (i.e., 16
    cp (hl)             ;       sectors).
    ret nz              ;       Return if not.
    push hl             ;       Stack HL pointer.
    ld c,15             ;       HL=address of 'CH_MODE' field of channel
    rst 40              ;       information (offset=+15).
    ld a,(hl)    
    cp #7F              ;       Jump forward if random access mode (#7F).
    jr z,CH_OUT03       ;#33EC
    ld hl,(CURCHL)      ;       Fetch address of current channel info.
    call WR_STMFENT     ;#3755  Write file entry to disk.
    call LOADBUFF       ;#3F96  Recover printer buffer contents.
    pop hl              ;       Unstack HL pointer.
    jp NEWSEGMT01       ;#340D  Jump forward and save new segment file.

CH_OUT03                ;#33EC
    pop hl              ;       Unstack HL pointer.
    push hl             ;       Stack HL pointer.
    call SEEKNXTSEG     ;#345D  Seek for next segment of the stream file.
    push af             ;       Stack Z flag (1=segment found).
    call z,RD_CHBUFF    ;#34A9  Read sector of current cursor position if 
                        ;       segment was found.
    pop af              ;       Unstack Z flag (1=segment found).
    pop hl              ;       Unstack HL pointer.
    call nz,NEWSEGMT    ;#3404  Save new segment file if it does not exist.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: GET SEGMenT
; Address: #33FB/13307
; Return stream file segment ID from channel information block.
; Input:  HL=address of 'MSB of file length' field of channel information.
; Output: D=#20/32, E=stream file segment ID.
; Called by: NEWSEGMT.
;------------------------------------------------------------------------------
GETSEGMT                ;#33FB
    ld (hl),0           ;       Reset MSB of file length.
    ld c,25             ;       HL=address of 'CH_SGMT' field of channel 
    rst 40              ;       information block (offset=+25).
    ld d,#20            ;       D=#20/32.
    ld e,(hl)           ;       E=segment number.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: NEW SEGMenT
; Address: #3404/13316
; Save new segment file for a stream.
; Called by: CH_OUT02.
;------------------------------------------------------------------------------
NEWSEGMT                ;#3404
    call GETSEGMT       ;#33FB  Get current segment ID and store in the system
    ld (VAR_A),de       ;       variable.
    jr NEWSEGMT02       ;#3415

;------------------------------------------------------------------------------
; NEWSEGMT01 (#340D/13325)
; This entry point save segment with incremented ID value.
; Called by: CH_OUT02.
;------------------------------------------------------------------------------
NEWSEGMT01              ;#340D
    call GETSEGMT       ;#33FB  Get current segment ID.
    inc e               ;       Increment segment ID and store in the system
    ld (VAR_A),de       ;       variable to save next segment

;------------------------------------------------------------------------------
; NEWSEGMT02 (#3415/13333)
; Save new segment file for a stream.
; Input: (VAR_A_L)=segment of stream file (LSB of parameter 1);
;        (VAR_A_H)=#20/32 (MSB of parameter 1).
; Called by: NEWSEGMT, CH_OUT02, RNDRECORD.
;------------------------------------------------------------------------------
NEWSEGMT02              ;#3415
    call SV_SGMT        ;#332E  Save stream segment file.
    ld c,16             ;       HL=address of 'CH_FNAM' field of channel 
    rst 40              ;       information block (offset=+16).
    ex de,hl            ;       DE=address of 'CH_FNAM'.
    ld hl,FILENAME      ;       Copy 16 bytes of directory entry stored at DOS 
    ld bc,16            ;       system variables (starting at FILENAME) to 
    ldir                ;       channel info.
    ld c,12             ;       HL=address of 'CH_ENTR' field of channel
    rst 40              ;       information block (offset=+12).
    ld a,(FILEPOS)      ;       Copy file entry position of DOS system variable
    ld (hl),a           ;       to corresponding channel info field.
    jp LOADBUFF         ;#3F96  Finish routine after recovering printer buffer
                        ;       contents from track 0/sector 9 of disk.

;------------------------------------------------------------------------------
; Subroutine: INPut NeXT CHaRacter
; Address: #342E/13358
; Move cursor to the next position. If end of channel buffer is reached, read
;next sector of stream file.
; Called by: CH_INP01.
;------------------------------------------------------------------------------
INPNXTCHR               ;#342E
    ld c,13             ;       HL=address of 'CH_DCUR' field of channel
    rst 40              ;       information block (offset=+13).
    inc (hl)            ;       Increment LSB of cursor position.
    ret nz              ;       Return if not end of the channel buffer
                        ;       (i.e. LSB is not 0 after increment).
    inc hl              ;       Move pointer to MSB of cursor position and 
    inc (hl)            ;       increment its value.
    push hl             ;       Stack address.
    call STREAMDRV      ;#34D4  Select drive with stream file.
    ld c,35             ;       HL=address of 'CH_FLSH' field of channel 
    rst 40              ;       information block (offset=+35).
    ld a,(hl)
    or a                ;       Jump forward if 'flush' flag is 0, i.e. not 
    jr z,INPNXTCHR01    ;#3449  write channel buffer contents into disk.
    pop hl              ;       Unstack adddress.
    push hl             ;       Stack adddress.
    dec (hl)            ;       Decrement MSB of cursor. This will fool
                        ;       CURSSECT to point one sector before current
                        ;       position of stream file cursor.
    call WR_CHBUFF      ;#348D  Write channel buffer to that sector.
    pop hl              ;       Unstack adddress.
    push hl             ;       Stack adddress.
    inc (hl)            ;       Restore MSB of cursor position.

INPNXTCHR01             ;#3449
    call RD_CHBUFF      ;#34A9  Fill buffer with sector of current cursor
                        ;       position.
    pop hl              ;       Unstack address of MSB of 'CH_DCUR' field.
    ld a,16             ;       Check if exceeded boundary of 4096 bytes.
    cp (hl)
    call z,NEXTSEGMT    ;#3454  Fill buffer with next segment if it has been
                        ;       exceeded.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: NEXT SEGMentT
; Address: #3454/13396
; Seek for next segment of stream file and read current sector into channel
;buffer. Raise error condition if next segment does not exist.
; Called by: INPNXTCHR.
;------------------------------------------------------------------------------
NEXTSEGMT               ;#3454
    call SEEKNXTSEG     ;#345D  Seek next segment of stream file.
    jp nz,ER_ENDFILE    ;#3520  Jump to 'end of file' error handler if segment
                        ;       does not exist.
    jp RD_CHBUFF        ;#34A9  Read sector of current cursor position.

;------------------------------------------------------------------------------
; Subroutine: SEEK NeXT SEGment
; Address: #345D/13405
; Seek next segment of a stream file.
; Input:  HL=address of MSB of 'CH_DCUR' field of channel information block.
; Output: Z flag=0 (file not found),
;               =1 (file found);
;         A=0 (file found).
; Called by: CH_OUT02, NEXTSEGMT.
;------------------------------------------------------------------------------
SEEKNXTSEG              ;#345D
    ld (hl),0           ;       Reset MSB of cursor position.
    ld c,25             ;       HL=address of 'CH_SGMT' field of channel 
    rst 40              ;       information block (offset=+25).
    inc (hl)            ;       Increment segment number.
    ld c,16             ;       HL=address of 'CH_FNAM' field of channel 
    rst 40              ;       information block (offset=+16).
    ld de,FILENAME      ;       DE=start address of directory entry.
    ld bc,16            ;       All directory entry (16 bytes) will be copied.
    ldir                ;       Copy directory entry of channel info to DOS
                        ;       system variables.
    call SEEKFILE01     ;#2D4C  Seek file in the directory.
    ret nz              ;       Return if file not found.

;------------------------------------------------------------------------------
; Subroutine: ReaD STreaM File ENTry
; Address: #3472/13426
; Read directory entry data and entry position from disk and write into channel
;information block.
; Output: A=0;
;         Z flag=1.
; Called by: SEEKNXTSEG, GETRECORD, RNDRECORD02.
;------------------------------------------------------------------------------
RD_STMFENT              ;#3472
    call GETENTRY       ;#27AE  Get directory entry.
    call LOADBUFF       ;#3F96  Restore printer buffer from disk.
    ld c,16             ;       HL=address of 'CH_FNAM' field of channel 
    rst 40              ;       information block (offset=+16)
    ex de,hl            ;       DE=destination address for copy.
    ld hl,FILENAME      ;       Source address for copy.
    ld bc,16            ;       All directory entry (16 bytes) will be copied.
    ldir                ;       Copy directory entry read from disk to channel
                        ;       information block.
    ld c,12             ;       HL=address of 'CH_ENTR' field of channel
    rst 40              ;       information block (offset=+12).
    ld a,(FILEPOS)      ;       Position of entry in the directory is saved 
    ld (hl),a           ;       into channel info field.
    xor a               ;       A=0 and Z flag=1.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: WRite CHannel BUFFer
; Address: #348D/13453
; Write channel buffer into the current sector of stream file. In write access 
;mode, buffer is cleared.
; Called by: CH_OUT02, INPNXTCHR, SELWRTCBF, FLUCHBUFF.
;------------------------------------------------------------------------------
WR_CHBUFF               ;#348D
    call CURSSECT       ;#34B4  DE=track/sector ID of current cursor position.
    call CHANBUFF       ;#33B5  HL=start address of channel buffer.
    ld b,1              ;       Transfer 1 sector (256 bytes).
    call WRSECTORS      ;#2EFA  Write channel buffer to disk.
    ld c,15             ;       HL=address of 'CH_MODE' field of channel
    rst 40              ;       information block.
    ld a,(hl)    
    cp #7F              ;       Return from subroutine if mode is random access
    ret z               ;       (#7F).
    call CHANBUFF       ;#33B5  HL=start address of channel buffer.
    xor a               ;       A=0.
    ld b,a              ;       B=0, counter for 256 bytes.

WR_CHBUFF01             ;#34A4
    ld (hl),a           ;       Reset memory pointed by HL.
    inc hl              ;       Increment pointer.
    djnz WR_CHBUFF01    ;#34A4  Repeat until all bytes of channel buffer are 0.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: ReaD CHannel BUFFer
; Address: #34A9/13481
; Read sector of current stream file cursor position and write to channel 
;buffer.
; Called by: CH_OUT02, INPNXTCHR, NEXTSEGMT, RNDRECORD.
;------------------------------------------------------------------------------
RD_CHBUFF               ;#34A9
    call CURSSECT       ;#34B4  D=track/E=sector of current cursor position.
    call CHANBUFF       ;#33B5  HL=start address of channel buffer.
    ld b,1              ;       Transfer 1 sector (256 bytes).
    jp RDSECTORS        ;#2EEA  Read last sector of file to buffer.

;------------------------------------------------------------------------------
; Subroutine: CURSor SECTor
; Address: #34B4/13492
; Fetch current cursor position and return corresponding sector/track ID of
;stream file segment. 
; Output: E=sector in stream file segment.
;         D=track where that sector is in.
; Note: this subroutine preserves A register. 
; Called by: INITSTREAM, WR_CHBUFF, RD_CHBUFF.
;------------------------------------------------------------------------------
CURSSECT                ;#34B4
    ld hl,(CURCHL)      ;       Fetch current channel info block address.
    ld bc,30            ;       HL=address of 'CH_FSEC' field of channel
    add hl,bc           ;       information block (offset=+30).
    ld e,(hl)           ;       E=start sector ID.
    inc hl              ;       Advance pointer to the next field.
    ld d,(hl)           ;       D=start track ID.
    ld c,14             ;       HL=address of MSB of 'stream file cursor' field
    rst 40              ;       of channel info (offset=+14).
    ld b,(hl)           ;       B=MSB of cursor position.
    dec b    
    inc b               ;       Check if B=0 (Z flag holds result).
    push af             ;       Save A onto stack.
    ld a,16             ;       Max value of sector number plus 1.
    jr z,CURSSECT03     ;#34D2  Jump forward if B=0 to skip next loop.

CURSSECT01              ;#34C9
; This loop increments sector/track value.
    inc e               ;       Increment sector number.
    cp e                ;       Check if sector number exceeds limit (>15).
    jr nz,CURSSECT02    ;#34D0  Jump forward if did not.
    ld e,0              ;       Otherwise, reset sector number and increment
    inc d               ;       track number.

CURSSECT02              ;#34D0
    djnz CURSSECT01     ;#34C9  Execute next pass of loop or exit it. 

CURSSECT03              ;#34D2
; Exit subroutine.
    pop af              ;       Restore A from stack.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: STREAM DRiVe
; Address: #34D4/13524
; Select the drive that contains stream file.
; Called by: CH_OUT02, INPNXTCHR, RNDRECORD, SELWRTCBF, WR_STMFENT.
;------------------------------------------------------------------------------
STREAMDRV               ;#34D4
    ld c,11             ;       HL=address of 'CH_DRIV' field in the channel
    rst 40              ;       information block (offset=+11).
    ld a,(hl)           ;       Fetch value of drive that holds stream file and
    jp SEL_DRIVE01      ;#3D74  turn it the current drive.

;------------------------------------------------------------------------------
; Subroutine: CHannel OUTput 01
; Address: #34DB/13531
; Main code of CH_OUTPUT (#3C0F/15375) routine.
;------------------------------------------------------------------------------
CH_OUT01                ;#34DB
    push hl             ;       Stack ROM_BASIC address (assigned by ROMBETA_R)
                        ;       to return by subroutine that enable BASIC ROM.
    ld hl,IF1VSWP       ;#318C  Stack address of that subroutine. This is the 
    push hl             ;       return address of the CH_OUTPUT routine.
    push af             ;       Stack output character.
    call IF1VSWP        ;#318C  Save Interface 1 extended system variables.
    ld a,10             ;       Include segment ID comparison when seeking for 
    ld (CMP_SIZE),a     ;       a file.
    pop af              ;       Unstack output character.
    call CHOUT_RND      ;#3532  Random mode stream output is treated.
    push af             ;       Stack output character.
    call READMODE       ;#36C1  Raise 'invalid stream' error condition if 
    jp z,ER_INVSTM      ;#352E  stream is in read mode.
    pop af              ;       Unstack output character.
    call CHBUFFADD      ;#33AB  HL=address of cursor within channel buffer.
    ld (hl),a           ;       Put output character into channel buffer.
    jp CH_OUT02         ;#33BE  Jump backward.

;------------------------------------------------------------------------------
; Subroutine: END of STreaM FiLe  XXXXXX
; Address: #34FC/13564
; Check if cursor reached end of stream file.
; Called by: CH_INP01.
;------------------------------------------------------------------------------
ENDSTMFL                ;#34FC
    ld c,13             ;       HL=address of CH_DCUR field of channel
    rst 40              ;       information block (offset=+13).
    ld a,(hl)           ;       A=LSB of cursor position.
    ld bc,14            ;       HL=address of CH_FPR2 field of channel 
    add hl,bc           ;       information block (offset=+27).
    cp (hl)             ;       Return if LSB of cursor position and of 
    ret nz              ;       parameter2 differs (not end of file).
    ld c,14             ;       HL=address of MSB of CH_DCUR field of channel 
    rst 40              ;       information block.
    ld a,(hl)           ;       A=MSB of file length.
    ld bc,14            ;       Offset=+28, MSB of CH_FPR2.
    add hl,bc
    cp (hl)             ;       Return if MSB of CH_FPR2 (#20/32) and of file  
    ret nz              ;       size differs.
    ld hl,CHANSCOPY     ;       This is the address of "K" channel info unless
    ld a,(hl)           ;       Interface 1 is connected.
    cp #F4              ;       This is LSB of PRINT-OUT routine, present in
                        ;       "K" channel info.
    jr z,ER_ENDFILE     ;#3520  Jump to 'end of file' error handler if 
                        ;       PRINT-OUT routine is found.
    bit 4,(hl)          ;       Otherwise, this address is FLAGS3. Jump to 'end
    jr z,ER_ENDFILE     ;#3520  of file' error handler if bit 4 is reset.
    or 1                ;       Otherwise, set flags C=0 and Z=0, remove return
    pop hl              ;       address from stack and return to IF1VSWP 
    ret                 ;       instead CH_INP01.

;------------------------------------------------------------------------------
; Error routine: END of FILE
; Address: #3520/13600
; This routine handles error raised after an attempt to read beyond last 
;segment of a stream file.
; Called by: NEXTSEGMT; ENDSTMFL.
;------------------------------------------------------------------------------
ER_ENDFILE              ;#3520
    ld a,7              ;       Code for '8 - End of file' error.

ER_INVSTM01             ;#3522
    ld (ERR_NR),a       ;       Define error code.
    call IF1VSWP        ;#318C  Restore Interface 1 system variables.
    ld hl,#0058         ;       (ERROR-3)+3. ERROR-3 is part of BASIC error 
                        ;       handler.
    jp CALLBAS          ;#2E36 Call BASIC ROM routine.

;------------------------------------------------------------------------------
; Error routine: INValid STreaM
; Address: #352E/13614
; This routine handles error raised when stream is accessed in wrong mode 
;(write mode for output or read mode for input).
; Called by: CH_OUT01, CH_INP01.
;------------------------------------------------------------------------------
ER_INVSTM               ;#352E
    ld a,23             ;       Code for 'O - Invalid Stream' error.
    jr ER_INVSTM01      ;#3522  Jump backward.

;------------------------------------------------------------------------------
; Subroutine: CHannel OUTput RND
; Address: #3532/13618
; Treat output character of random access mode stream. First fetch record 
;number, and then fill record with data.
; Called by: CH_OUT01.
;------------------------------------------------------------------------------
CHOUT_RND               ;#3532
; Check stream access mode and exit unless mode is random.
    ld d,a              ;       Save output character into D register.
    ld c,15             ;       HL=address of 'CH_MODE' field of channel 
    rst 40              ;       information block (offset=+15).
    ld a,(hl)           ;       Fetch mode of stream.
    cp #7F              ;       Check if mode is 'RND'.
    ld a,d              ;       Recover character.
    ret nz              ;       Exit subroutine if mode is not 'RND'.

    ld bc,19            ;       Pointer is moved to offset=+34 (CH_WREC).
    add hl,bc
    ld a,(hl)           ;       Fetch (CH_WREC) value and check if it is 0 
    or a                ;       (i.e. expecting record number argument).
    ld a,d              ;       Restore output character in A.  
    jr nz,CHOUT_RND02   ;#3565  Jump forward if record number is not expected.

    dec hl              ;       Pointer is moved to CH_WCUR (offset=+33).
    ld a,(hl)           ;       Fetch workspace cursor position.
    or a                ;       Jump forward if workspace is not empty, i.e.
    jr nz,CHOUT_RND01   ;#3552  (wscursor) is greater than 0. Otherwise, a new
                        ;       space will be created.

    push bc             ;       Stack B register (0).
    push hl             ;       Stack address of CH_WCUR field.
    push de             ;       Stack character code.
    call MK16BYTES      ;#3588  Open a space of 16 bytes in the workspace.
    pop de              ;       Unstack character code.
    pop hl              ;       Unstack address of CH_WCUR field.
    pop bc              ;       Unstack B register (0).

CHOUT_RND01             ;#3552
; The record number argument of PRINT# or INPUT# is collected character by
;character into the workspace. This is finished when character with code #06
;are found (comma print, it is generated when comma appears as separator in the 
;PRINT statement like 'PRINT #s;(r),x' or 'INPUT #s;(r),x'). It is supposed 
;that the argument received before the comma is record number.
    ld c,(hl)           ;       C=workspace cursor position.
    ld a,d              ;       A=output character.
    ex de,hl            ;       DE=address of wscursor field in channel info.
    ld hl,(WKSPADD)     ;       HL=start address of workspace.
    add hl,bc           ;       HL=current address of cursor in workspace.
    cp 6                ;       Check if code of character is 6 (comma print).
    ld (hl),a           ;       Put character into workspace.
    push de             ;       Stack address of wscursor field.
    call z,GETRECORD    ;#3594  Evaluate record position if character is comma 
                        ;       print.
    pop de              ;       Unstack address of wscursor field.
    ex de,hl            ;       HL=address of wscursor field in channel info.
    inc (hl)            ;       Increment cursor to the next position.
    pop hl              ;       Remove return address from stack and return to 
    ret                 ;       IF1VSWP instead CH_INP01 (character will not be
                        ;       stored into channel buffer).

CHOUT_RND02             ;#3565
; Record position argument has been fetched. Now record data is collected in
;the channel buffer until an end of line marker ('enter', #0D/13) is found or
;end of record is reached.
    dec hl              ;       Pointer is moved to offset=+33 (CH_WCUR).
    ld a,(hl)           ;       Fetch position of workspace cursor.
    dec hl              ;       Pointer is moved to offset=+32 (record length).
    inc a               ;       Include next character to calculate new value
    cp (hl)             ;       of wscursor and compare with record length 
                        ;       (CARRY=1 if there are space in the record yet).
    inc hl              ;       Pointer is moved to offset=+33 (CH_WCUR).
    inc (hl)            ;       Increment (wscursor) to include next character.
    push hl             ;       Stack address of wscursor.
    push af             ;       Stack CARRY flag.
    ld c,35             ;       HL=address of CH_FLSH field of channel info.
    rst 40              ;       Assign #FF to CH_FLSH flag, contents of channel
    ld (hl),#FF         ;       buffer must be written to disk.
    pop af              ;       Unstack CARRY flag.
    pop hl              ;       Unstack address of of wscursor.
    jr c,CHOUT_RND03    ;#357E  Jump forward if there are space in the record.
    ld a,d              ;       Otherwise, fetch character and check if it is 
    cp #0D              ;       'enter' (#0D/13).
    jr z,CHOUT_RND04    ;#3582  Jump forward if it is 'enter', otherwise remove 
    pop bc              ;       return address from stack and jump to IF1VSWP
    ret                 ;       instead CH_INP01. The output character will be
                        ;       discarded.

CHOUT_RND03             ;#357E
; Record space are not filled, thus return to put output character into channel 
;buffer unless end of line (#0D/13) is found.
    ld a,d              ;       Exit subroutine if character is not 'enter'.
    cp #0D              ;       Otherwise, stop to collecting characters to
    ret nz              ;       the record.

CHOUT_RND04             ;#3582
; Record will not accept any character furthermore.
    xor a               ;       Reset CH_WCUR to treat next record.
    ld (hl),a    
    inc hl              ;       Reset CH_WREC flag, expect record
    ld (hl),a           ;       number in further output operation.
    ld a,d              ;       Copy output character in A.
    ret                 ;       Exit subroutine.

;------------------------------------------------------------------------------
; Subroutine: MaKe 16 BYTES
; Address: #3588/13704
; Create 16 bytes long space into BASIC workspace.
; Output: (WKSPADD)=start address of created space.
; Called by: CHOUT_RND.
;------------------------------------------------------------------------------
MK16BYTES               ;#3588
    ld hl,(WORKSP)      ;       Fetch start address of workspace.
    ld (WKSPADD),hl     ;       Store address of the space to be opened.
    ld bc,16            ;       The new space will be 16 bytes long.
    jp BAS_BCSPC        ;#2EC2  Jump to the routine for creating space.

;------------------------------------------------------------------------------
; Subroutine: GET RECORD
; Address: #3594/13716
; Record number argument has been collected from PRINT#/INPUT# statement and
;saved in the workspace. Argument is evaluated and requested record in stream
;is selected.
; Called by: CHOUT_RND. 
;------------------------------------------------------------------------------
GETRECORD               ;#3594
    ld (hl),#0D         ;       Put end of line marker (enter) into workspace.
    ld hl,(CH_ADD)      ;       Save content of CH_ADD temporarily into VAR_A.
    ld (VAR_A),hl
    ld hl,(WKSPADD)     ;       BASIC interpreter cursor is placed at start of
    ld (CH_ADD),hl      ;       workspace.
    ld hl,FLAGS         ;       Reset bit 7 of FLAGS, BASIC is now in syntax 
    res 7,(hl)          ;       checking mode.
    call BAS_E1NUM      ;#2E5D  
    ld hl,FLAGS         ;       Set bit 7 of FLAGS, BASIC is in execution mode.
    set 7,(hl)
    ld hl,(WKSPADD)     ;       BASIC interpreter cursor is placed at start of
    ld (CH_ADD),hl      ;       workspace.
    call BAS_E1NUM      ;#2E5D  Get number from the line in workspace.
    call BAS_FDINT      ;#2E53  Transfer integer number from calculator stack 
    push bc             ;       to BC register pair; this value is copied to DE
    pop de              ;       register pair.
    ld c,32             ;       HL=address of CH_RLEN field of channel
    rst 40              ;       information block.
    ld b,(hl)           ;       Fetch record length.
    xor a               ;       Reset CARRY flag.
    ld hl,0             ;       Reset bits 0-15 of 32-bit accumulator.
    ld (VAR_C),hl       ;       Reset bits 16-31 of 32-bit accumulator.

GETRECORD01             ;#35C8
; This is 32-bit multiplication routine. (VAR_C) and HL holds the result, DE is
;multiplicand and B is multiplier.
    add hl,de           ;       Multiplication is achieved by successive 
                        ;       additions.
    jr nc,GETRECORD02   ;#35D4  Jump forward unless result fits in 16 bits
                        ;       (i.e. no CARRY).
    push hl             ;       Stack partial result.
    ld hl,(VAR_C)       ;       Fetch most significant bytes and increment.
    inc hl    
    ld (VAR_C),hl
    pop hl              ;       Unstack partial result.
GETRECORD02             ;#35D4
    djnz GETRECORD01    ;#35C8  Decrement multiplier and repeat until it is 0.

; The result of multiplication is the position of record given in bytes. This
;value will be modified to give: (VAR_B_L)=position of record into the sector,
;(VAR_B_H)=ID of segment where record is in and (VAR_C_L)=ID of sector where
;record is in.
    ld (VAR_B),hl       ;       Store bits 0-15 of result into variable.
    ld a,(VAR_C_L)      ;       Fetch bits 16-23 of result.
    ld hl,VAR_B_H       ;       A and (HL) hold bits 8-23 (number of sectors).
    rrd                 ;       (HL)=(numb. sectors)/16 and A=remainder
    and #0F             ;       Mask out bits 4-7 (A=sector within segment).
    ld (VAR_C_L),a
    ld hl,(VAR_A)       ;       Recover saved content of CH_ADD from VAR_A.
    ld (CH_ADD),hl
    call RNDRECORD      ;#35F8  Adjust cursor position to the requested record.
    ld c,33             ;       HL=address of CH_WCUR field of channel 
    rst 40              ;       information block.
    ld a,#FF            ;       Assign -1 value to cursor, this variable will
    ld (hl),a           ;       count number of characters sent to the record.
    inc hl              ;       Assign #FF value to CH_WREC flag, next output 
    ld (hl),a           ;       is directed to fill record.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: RND RECORD
; Address: #35F8/13816
; Take record position of random acess mode stream file and adjust cursor of
;channel information block. Segment file can be loaded or created when 
;neccessary.
; Input:  (VAR_B_L)=position of record in the sector;
;         (VAR_C_L)=ID of the sector;
;         (VAR_B_H)=ID of the segment file.
; Called by: GETRECORD.
;------------------------------------------------------------------------------
RNDRECORD               ;#35F8
    ld hl,(CURCHL)      ;       Fetch current channel address and save onto
    push hl             ;       stack.
    ld bc,25            ;       HL=address of CH_SGMT field of channel 
    add hl,bc           ;       information block (offset=+25).
    ld a,(VAR_B_H)      ;       Compare requested segment ID with the current
    cp (hl)             ;       value.
    jp nz,RNDRECORD02   ;#361B  Jump forward if they differ.
    pop hl              ;       Unstack current channel address.
    ld bc,14            ;       HL=address of MSB of CH_DCUR field of channel
    add hl,bc           ;       information block (offset=+14).
    ld a,(VAR_C_L)      ;       Fetch requested value of MSB of cursor (i.e.,
    cp (hl)             ;       sector where cursor is in) and compare with ID
    jp nz,RNDRECORD03   ;#3643  in channel info. Jump forward if they differ.

RNDRECORD01             ;#3613
; Update LSB of cursor position and return.
    ld c,13             ;       HL=address of LSB of CH_DCUR field of channel
    rst 40              ;       information block (offset=+14).
    ld a,(VAR_B_L)      ;       Update LSB of cursor position with the position 
    ld (hl),a           ;       of record in the sector.
    ret                 ;       End of subroutine.

RNDRECORD02             ;#361B
; Current segment is not the requested one. Read requested segment from disk
;or, if it is not there, make a new segment.
    call FLUSHCBUF      ;#3666  First, flush channel buffer ot disk if
    call nz,SELWRTCBF   ;#365F  neccessary.
    ld a,(VAR_B_H)      ;       Fetch requested segment ID.
    pop hl              ;       Unstack current channel address.
    push hl             ;       Stack current channel address.
    ld bc,25            ;       HL=address of CH_SGMT field of channel
    add hl,bc           ;       information block (offset=+25).
    ld (hl),a           ;       The requested ID is now the current segment ID.
    pop hl              ;       Unstack current channel address.
    ld bc,16            ;       HL=address of CH_FNAM field of channel 
    add hl,bc           ;       information block (offset=+16).
    ld de,FILENAME      ;       DE=start address of dir entry in DOS variables.
    ld bc,16            ;       Length of a directory entry.
    ldir                ;       Copy entry from channel buffer to variables.
    call SEEKFILE01     ;#2D4C  Seek for the file.
    jp nz,RNDRECORD05   ;#366E  Jump forward to make new segment if not found.
    call RD_STMFENT     ;#3472  Read directory entry from disk, write to 
    jr RNDRECORD04      ;#3649  channel buffer and jump forward.

RNDRECORD03             ;#3643
    call FLUSHCBUF      ;#3666  First, flush channel buffer ot disk if
    call nz,SELWRTCBF   ;#365F  neccessary.

RNDRECORD04             ;#3649
; Read requested sector (MSB of cursor position) into channel buffer.
    ld a,(VAR_C_L)      ;       Fetch requested MSB of cursor position.
    ld c,14             ;       HL=address of MSB of CH_DCUR field of channel 
    rst 40              ;       information block (offset=+14)
    ld (hl),a           ;       Update this value into channel info block.
    push hl             ;       Stack address of MSB of cursor position.
    call STREAMDRV      ;#34D4  Select drive with stream file.
    call RD_CHBUFF      ;#34A9  Read channel buffer from segment.
    pop hl              ;       Unstack pointer and decrement to offset=+13 
    dec hl              ;       (LSB of CH_DCUR).
    ld a,(VAR_B_L)      ;       Fetch requested value of LSB of cursor and
    ld (hl),a           ;       update this field into channel info block.
    jr RNDRECORD01      ;#3613  Jump backward to finish subroutine (note: it
                        ;       should be 'ret' instead 'jr' for faster
                        ;       execution and shorter code).

;------------------------------------------------------------------------------
; Subroutine: SELect WRiTe Channel BuFfer
; Address: #365F/13919
; Select drive and write channel buffer to disk.
; Called by: RNDRECORD.
;------------------------------------------------------------------------------
SELWRTCBF               ;#365F
    call STREAMDRV      ;#34D4  Select drive with stream file.
    call WR_CHBUFF      ;#348D  Write channel buffer to disk.
    ret   
 
;------------------------------------------------------------------------------
; Subroutine: FLUSH Channel BUFfer
; Address: #3666/13926
; Check if channel buffer must be flushed in random access mode.
; Output: Z flag=0 if channel buffer must be flushed.
; Called by: RNDRECORD.
;------------------------------------------------------------------------------
FLUSHCBUF               ;#3666
    ld c,35             ;       HL=address of CH_FLSH field of channel 
    rst 40              ;       information block (offset=+35).
    ld a,(hl)           ;       Fetch value and compare with 0.
    or a    
    ld (hl),0           ;       Reset 'flush' flag.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; RNDRECORD05 (#366E/13934)
; Continuation of RNDRECORD (#35F8/13816).
;------------------------------------------------------------------------------
RNDRECORD05             ;#366E
; Make a new stream segment file.
    ld hl,(VAR_B_H)     ;       Fetch segment number in L register.
    ld h,#20            ;       MSB is always #20.
    ld (VAR_A),hl       ;       Store file parameter 1 into DOS variable.
    ld hl,(VAR_B)       ;       Save contents of (VAR_B) onto stack.
    push hl    
    ld hl,(VAR_C)       ;       Save contents of (VAR_C) onto stack.
    push hl    
    call NEWSEGMT02     ;#3415
    pop hl              ;       Restore contents of (VAR_C) from stack.
    ld (VAR_C),hl
    pop hl              ;       Restore contents of (VAR_B) from stack.
    ld (VAR_B),hl
    jr RNDRECORD04      ;#3649  Jump backward to update cursor position and
                        ;       finish.

;------------------------------------------------------------------------------
; Routine: CHannel INPut 01
; Address: #34DB/13531
; Main code of CH_INPUT (#3C09/15369).
;------------------------------------------------------------------------------
CH_INP01                ;#368B
    push hl             ;       Stack ROM_BASIC address (assigned by ROMBETA_R)
                        ;       to return by subroutine that enable BASIC ROM.
    ld hl,IF1VSWP       ;#318C  Stack IF1VSWP to be used as return address 
    push hl             ;       (IF1 system variables will be recovered).
    call IF1VSWP        ;#318C  Save Interface 1 ROM system variables.
    ld hl,TVFLAG        ;       Reset bit 3 of TV flag, mode has not been
    res 3,(hl)          ;       changed.
    xor a               ;       Reset duration of key click tone.
    ld (PIP),a
    ld a,10             ;       Include segment ID to file comparison routines.
    ld (CMP_SIZE),a
    call READMODE       ;#36C1  Check if stream is in read mode.
    jr z,CH_INP02       ;#36B3  Jump forward if it is.
    cp #7F              ;       Raise 'invalid stream error' condition if mode
    jp nz,ER_INVSTM     ;#352E  is not random access (#7F).
    ld bc,19            ;       Move pointer to CH_WREC field of channel info
    add hl,bc           ;       block (former position was +15=CH_MODE).
    ld (hl),0           ;       Reset (CH_WREC), wait for record length if
                        ;       random mode.
    jr CH_INP03         ;#36B6  Skip cursor position checking.

CH_INP02                ;#36B3
    call ENDSTMFL       ;#34FC  Check if cursor reached end of stream file.

CH_INP03                ;#36B6
    call CHBUFFADD      ;#33AB  HL=address of cursor within channel buffer.
    ld a,(hl)           ;       Fetch character from channel buffer.
    push af             ;       Stack character code.
    call INPNXTCHR      ;#342E  Advance cursor to the next position.
    pop af              ;       Unstack character code.
    scf                 ;       Notice BASIC monitor that a character has been
    ret                 ;       picked (CARRY flag=1) and return.

;------------------------------------------------------------------------------
; Subroutine: READ MODE
; Address: #36C1/14017
; Check if stream file was opened in read mode ("R").
; Output: Z flag=1 for write mode;
;         A=mode (#00, #7F or #FF).
; Called by: CH_OUT01, CH_INP01.
;------------------------------------------------------------------------------
READMODE                ;#36C1
    ld c,15             ;       HL=address of CH_MODE field of channel
    rst 40              ;       information block (offset=+15)
    ld a,(hl)           ;       Check if it is read mode (#00).
    or a                ;       Z flag=1 for read mode.
    ret                 ;       End of subroutine.
  
;==============================================================================
; DOS Statement: CLOSE 
; Address: #36C7/14023
; Close a stream file.
; Syntax: CLOSE #<s>        (s=stream ID, 4-15)
;==============================================================================
DS_CLOSE                ;#36C7
    ld hl,(DSTMADDR)    ;       BASIC interpreter cursor is placed at start of
    ld (CH_ADD),hl      ;       DOS command line.
    call GETARG_I       ;#2EA8  Get stream number from command line.
    call SYN_CHCK       ;#2E0E  Return if DOS is in syntax checking mode.
    ld a,(VAR_C_L)      ;       Fetch stream number.
    ld hl,#1727         ;       Call STR-DATA1 (#1727/5627) routine of BASIC 
    call CALLBAS        ;#2E36  ROM to get stream data.
    ld a,b              ;       Closed stream returns BC=0, opened stream
    or c                ;       returns offset value from (CHANS).
    jp z,DSTM_RET       ;#2170  Exit DS_CLOSE routine if stream is closed.
    push hl             ;       Stack address of stream data.
    ld hl,(CHANS)       ;       Add offset to (CHANS) and get address of second 
    add hl,bc           ;       byte at channel information area.
    ld a,(hl)           ;       Fetch the second byte of channel.
    ld hl,CH_OUTPUT     ;#3C0F  Compare with MSB of CH_OUTPUT to check if
    cp h                ;       stream is a disk file.
    pop hl              ;       Unstack address of stream data.
    jp nz,ER_NDFILE     ;#32BC  Raise error condition if trying to close a
                        ;       channel other than of stream file.
    ld (hl),0           ;       Close stream, attributting 0 to offset value
    inc hl              ;       (LSB and MSB both bytes).
    ld (hl),0
    ld (VAR_B),bc       ;       Store offset value into DOS variable.
    ld hl,(CHANS)       ;       Add offset and (CHANS) to get address of second 
    add hl,bc           ;       byte of channel info.
    dec hl              ;       HL is pointing to first byte of channel info.
    ld (VAR_A),hl       ;       Save address into DOS variable. 
    call FLUCHBUFF      ;#3742  Write contents of channel buffer to disk.
    ld hl,(VAR_A)       ;       Start of channel info area to erase from RAM.
    ld bc,292           ;       292 bytes will be reclaimed.
    call BAS_RECLM      ;#2ED7  Erase channel info to free memory.
    ld hl,STRMS         ;       Pointer initialized to start of stream data.
    ld b,16             ;       16 streams (BUG: there are stream -3/#FD, 
                        ;      -2/#FE and -1/#FF before 0-15 that are not taken
                        ;       in account).
DS_CLOSE01              ;#3711
    push bc             ;       Stack stream counter.
    ld bc,(VAR_B)       ;       BC=data offset of closed stream.
    ld e,(hl)           ;       DC=data offset of stream being examined.
    inc hl
    ld d,(hl)
    ex de,hl            ;       HL=offset of channel being examined.
    sbc hl,bc           ;       Check if offset of this stream is greater than 
                        ;       offset of closed stream
    ex de,hl            ;       HL=pointer to stream data.
    jr c,DS_CLOSE02     ;#3730  Jump forward for stream with smaller offset.
    ld d,(hl)           ;       DE=data offset of stream.
    dec hl    
    ld e,(hl)    
    inc hl    
    push hl             ;       Stack stream data pointer.
    ex de,hl            ;       DE=data offset of stream.
    ld bc,292           ;       Displace offset by -292 bytes (because this
    sbc hl,bc           ;       amount of RAM was released).
    ex de,hl            ;       DE=new offset value.
    pop hl              ;       Unstack stream data pointer.
    ld (hl),d           ;       Replace stream offset by new one.
    dec hl    
    ld (hl),e    
    inc hl    

DS_CLOSE02              ;#3730
    inc hl              ;       Increment stream data pointer.
    pop bc              ;       Unstack stream counter.
    djnz DS_CLOSE01     ;#3711  Repeat for all streams.
    ld hl,(DSTMADDR)    ;       Subtract 292 bytes from DOS command line 
    ld bc,292           ;       pointer because this amount of RAM was 
    sbc hl,bc           ;       reclaimed, pulling down BASIC RAM.
    ld (DSTMADDR),hl
    jp DSTM_RET         ;#2170  Return to DOS interpreter.

;------------------------------------------------------------------------------
; Subroutine: FLUsh CHannel BUFFer
; Address: #3742/14146
; Flush contents of channel buffer to disk if it is in 'read mode'.
; Input:  HL=start address of channel info;
;         (VAR_A)=start address of channel info;
; Called by: DS_CLOSE.
;------------------------------------------------------------------------------
FLUCHBUFF               ;#3742
    ld bc,15            ;       HL=address of CH_MODE field of channel
    add hl,bc           ;       information block (offset=+15).
    ld a,(hl)           ;       Check if channel was opened in 'read mode'
    or a                ;       (i.e., CH_MODE is 0).
    ret z               ;       Return if read mode.
    ld hl,(VAR_A)       ;       Turn this channel the current channel.
    ld (CURCHL),hl
    call WR_STMFENT     ;#3755  Write stream file directory entry to disk.
    jp WR_CHBUFF        ;#348D  Write channel buffer to stream file.

;-----------------------------------------------------------------------------
; Subroutine: WRite STreaM File ENTry
; Address: #3755/14165
; Fetch directory entry data from channel information block and write to disk.
; Input:  HL=address of channel information block.
; Called by: CH_OUT02, FLUCHBUFF.
;-----------------------------------------------------------------------------
WR_STMFENT              ;#3755
    ld bc,13            ;       HL=address of CH_DCUR field of channel
    add hl,bc           ;       information block (offset=+13).
    ld e,(hl)           ;       DE=length of stream file.
    inc hl    
    ld d,(hl)    
    ld bc,13            ;       HL=address of CH_FPR2 field of channel
    add hl,bc           ;       information block (offset=+27).
    ld (hl),e           ;       (parameter2)=(file length).
    inc hl    
    ld (hl),d    
    ld c,16             ;       HL=start address of CH_FNAM field of channel
    rst 40              ;       information block (offset=+16)
    ld de,FILENAME      ;       Destination address is DOS system variables.
    ld bc,16            ;       Copy all 16 bytes of directory entry.
    ldir                ;       Copy entry from channel info to DOS variables.
    call STREAMDRV      ;#34D4  Select drive with stream file.
    ld c,12             ;       HL=address of CH_ENTR field of channel
    rst 40              ;       information block (offset=+12)
    ld c,(hl)           ;       Fetch directory entry position of stream file.
    call PUTENTRY       ;#27BC  Prepare directory entry in printer buffer and
    jp WRT_BUFFER       ;#2EF0  write to disk.

;------------------------------------------------------------------------------
; Subroutine: PRiNt STRing 01
; Address: #377B/14203
; Main routine of PRNSTR (RST #18/RST 24). Print sequence of characters until 
;end marker is found. Marker is 0 (which is not printed) or any byte with bit 7
;high (which is printed after bit 7 is lowered).
; INPUT: HL=string start address.
; Called by: PRNSTR, PRINTERR, OVERWRITE.
;------------------------------------------------------------------------------
PRNSTR01                ;#377B
    ld a,(hl)           ;       Take character from HL pointer.
    or a                ;       When 0 is found, finish subroutine without 
    ret z               ;       printing it.
    and %01111111       ;       Mask out bit 7.
    rst 16              ;       Print character.
    bit 7,(hl)          ;       Return if bit 7 of printed character is 1.
    ret nz
    inc hl              ;       Advance pointer 1 position and repeat.    
    jr PRNSTR01         ;#377B 

;------------------------------------------------------------------------------
; Subroutine: ComPare STRINGs
; Address: #3787/14215
; Compare two strings. Return with Z flag raised if strings are equal.
; Input:  DE=first string address
;         HL=second string address
;         B=length of string
; Output: Z flag=1 if two strings are equal.
; Called by: SEEKFILE.
;------------------------------------------------------------------------------
CP_STRING               ;#3787
    ld a,(de)           ;       Fetch byte at (DE) and compare with byte at
    cp (hl)             ;       (HL).
    ret nz              ;       Return if they are differents (Z flag=0).
    inc de              ;       Increment both pointers.
    inc hl    
    djnz CP_STRING      ;#3787  Repeat until all bytes are compared.
                        ;       Return with ZERO=1 if comparison is successful.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; ER_NODISK01 (#378F/14223)
; ER_NODISK (#3E82/16002) continues here. Disk was not detected in the drive.
;------------------------------------------------------------------------------ 
ER_NODISK01             ;#378F
    ld hl,M_NODISK      ;#37CF  Message: "No disk"
    ld a,6              ;       DOS error code 6.
    jp DSTM_ERRET       ;#2CE5  Jump to error handler.

;------------------------------------------------------------------------------
; Error routine: DIRectory FULL
; Address: #3797/11118
; The limit of 128 entries in the directory was exceeded.
; Called by: DIRFULL.
;------------------------------------------------------------------------------
ER_DIRFULL              ;#3797
    ld hl,M_DIRFULL     ;#37C0  Message: "Directory full".
    ld a,4              ;       DOS error code 4.
    jp DSTM_ERRET       ;#2CE5  Jump to error handler.

;------------------------------------------------------------------------------
; Subroutine: ERROR R 
; Address: #379F/14239
; Define "R - Tape loading error" error status.
; Called by: ER_NODISK, RDWRSECT.
;------------------------------------------------------------------------------
ERROR_R                 ;#379F
    ld a,26             ;       A=26, error code "R".
    jr DEF_ERRNR        ;#37A5  Jump to define system variable.

;------------------------------------------------------------------------------
; Subroutine: ERROR J
; Address: #37A3/14243
; Define "J – Invalid I/O device" error status.
;------------------------------------------------------------------------------
ERROR_J
    ld a,18             ;       A=18, error code "J".

;------------------------------------------------------------------------------
; Routine: DEFine ERR_NR
; Address: #37A5/14245
; Called by: ERROR_R, ERROR_J, ERROR_4.
;------------------------------------------------------------------------------
DEF_ERRNR               ;#37A5
    ld (ERR_NR),a       ;       Store error code into BASIC system variable.
    ret                 ;       End of routine.

;------------------------------------------------------------------------------
; Subroutine: ERROR 4
; Address: #37A9/14249
; Define "4 – Out of memory" error status.
;------------------------------------------------------------------------------
ERROR_4
    ld a,3              ;       A=3, error code "4".
    jr DEF_ERRNR        ;#37A5  Jump to define system variable.

;==============================================================================
; Messages (#37AD/14253-#380E/14350)
;==============================================================================
M_BREAK                 ;#37AD/14253
    defm "*BREAK*"
    defb #8D            ; #80+'Enter' (end of string marker).

M_OUT_RAM               ;#37B5/14261
    defm "Out of RAM"
    defb #8D            ; #80+'Enter' (end of string marker).

M_DIRFULL               ;#37C0/14272
    defm "Directory full"
    defb #8D            ; #80+'Enter' (end of string marker).

M_NODISK                ;#37CF/14287
    defm "No disk"
    defb #8D            ; #80+'Enter' (end of string marker).

M_STMOPEN               ;#37D7/14295
    defm "Stream opened"
    defb #8D            ; #80+'Enter' (end of string marker).

M_NODFILE               ;#37E5/14309
    defm "Not disk file"
    defb #8D            ; #80+'Enter' (end of string marker).

M_F_EXST                ;#37F3/14323
    defm "File exists"
    defb #0D            ; 'Enter'
    defm "Over write?"
    defm "(Y/N"
    defb #A9            ; ")"+#80 (end of string marker).
;==============================================================================

;------------------------------------------------------------------------------
; Unused bytes and codes (#380F/14351-#38F0/14576)
;------------------------------------------------------------------------------
    push af             ;380f    f5     . 
    push bc             ;3810    c5     . 
    ld (DETEMP),de      ;3811    ed 53 04 5d     . S . ] 
    ld (HLTEMP),hl      ;3815    22 02 5d     " . ] 
    call IF1VSWP        ;3818    cd 8c 31     . . 1 
    ld a,#FF            ;381b    3e ff     > . 
    ld (RM_FPC),a       ;381d    32 1f 5d     2 . ] 
    pop bc              ;3820    c1     . 
    pop af              ;3821    f1     . 
    ld hl,BASDOSRET     ;3822    21 a4 21     ! . ! 
    ld (DOS_RET),hl     ;3825    22 1a 5d     " . ] 
    ld hl,0             ;3828    21 00 00     ! . . 
    add hl,sp           ;382b    39     9 
    ld (OLDSP),hl       ;382c    22 1c 5d     " . ] 
    dec hl              ;382f    2b     + 
    dec hl              ;3830    2b     + 
    ld sp,hl            ;3831    f9     . 
    push af             ;3832    f5     . 
    call DEF_ERRSP      ;3833    cd c0 21     . . ! 
    ld hl,0385ah        ;3836    21 5a 38     ! Z 8 
    ld a,(hl)           ;3839    7e     ~ 
    cp c                ;383a    b9     . 
    jr nz,$+20          ;383b    20 12       . 
    pop af              ;383d    f1     . 
    inc hl              ;383e    23     # 
    ld e,(hl)           ;383f    5e     ^ 
    inc hl              ;3840    23     # 
    ld d,(hl)           ;3841    56     V 
    ld hl,DSTM_RET      ;3842    21 70 21     ! p ! 
    push hl             ;3845    e5     . 
    push de             ;3846    d5     . 
    ld hl,(HLTEMP)      ;3847    2a 02 5d     * . ] 
    ld de,(DETEMP)      ;384a    ed 5b 04 5d     . [ . ] 
    ret                 ;384e    c9     . 
    cp #FF              ;384f    fe ff     . . 
    jr nz,$+4           ;3851    20 02       . 
    pop af              ;3853    f1     . 
    ret                 ;3854    c9     . 
    inc hl              ;3855    23     # 
    inc hl              ;3856    23     # 
    inc hl              ;3857    23     # 
    jr $-31             ;3858    18 df     . . 
    nop                 ;385a    00     . 
    dec a               ;385b    3d     = 
    dec a               ;385c    3d     = 
    ld bc,SEL_DRIVE01   ;385d    01 74 3d     . t = 
    ld (bc),a           ;3860    02     . 
    inc c               ;3861    0c     . 
    ld a,3              ;3862    3e 03     > . 
    sbc a,e             ;3864    9b     . 
    ld a,4              ;3865    3e 04     > . 
    sbc a,a             ;3867    9f     . 
    ld a,5              ;3868    3e 05     > . 
    jp pe,#062E         ;386a    ea 2e 06     . . . 
    jp m,#072E          ;386d    fa 2e 07     . . . 
    sbc a,d             ;3870    9a     . 
    jr c,$+10           ;3871    38 08     8 . 
    xor l               ;3873    ad     . 
    daa                 ;3874    27     ' 
    add hl,bc           ;3875    09     . 
    or l                ;3876    b5     . 
    daa                 ;3877    27     ' 
    ld a,(bc)           ;3878    0a     . 
    adc a,c             ;3879    89     . 
    dec l               ;387a    2d     - 
    dec bc              ;387b    0b     . 
    cp l                ;387c    bd     . 
    jr c,$+14           ;387d    38 0c     8 . 
    or h                ;387f    b4     . 
    jr c,$+15           ;3880    38 0d     8 . 
    ld (hl),b           ;3882    70     p 
    ld hl,#D10E         ;3883    21 0e d1     ! . . 
    jr c,$+17           ;3886    38 0f     8 . 
    ld (hl),b           ;3888    70     p 
    ld hl,#7010         ;3889    21 10 70     ! . p 
    ld hl,#7011         ;388c    21 11 70     ! . p 
    ld hl,#E812         ;388f    21 12 e8     ! . . 
    jr c,$+21           ;3892    38 13     8 . 
    and d               ;3894    a2     . 
    jr c,$+22           ;3895    38 14     8 . 
    and l               ;3897    a5     . 
    jr c,$+1            ;3898    38 ff     8 . 
    push af             ;389a    f5     . 
    call ID_TYPE        ;389b    cd 84 23     . . # 
    pop af              ;389e    f1     . 
    jp #23f6            ;389f    c3 f6 23     . . # 
    xor a               ;38a2    af     . 
    jr $+4              ;38a3    18 02     . . 
    ld a,#FF            ;38a5    3e ff     > . 
    ld de,FILENAME      ;38a7    11 dd 5c     . . \ 
    ld bc,16            ;38aa    01 10 00     . . . 
    or a                ;38ad    b7     . 
    jr z,$+3            ;38ae    28 01     ( . 
    ex de,hl            ;38b0    eb     . 
    ldir                ;38b1    ed b0     . . 
    ret                 ;38b3    c9     . 
    call ID_TYPE        ;38b4    cd 84 23     . . # 
    call DIRFULL        ;38b7    cd 6e 2b     . n + 
    jp #2BD1            ;38ba    c3 d1 2b     . . + 
    ld (VAR_A_L),hl     ;38bd    22 d7 5c     " . \ 
    ld (VAR_B_L),de     ;38c0    ed 53 d9 5c     . S . \ 
    ld (VAR_C_L),de     ;38c4    ed 53 db 5c     . S . \ 
    call ID_TYPE        ;38c8    cd 84 23     . . # 
    call DIRFULL        ;38cb    cd 6e 2b     . n + 
    jp DS_SAVE07        ;38ce    c3 fd 2b     . . + 
    or a                ;38d1    b7     . 
    ld (CODEARG),a      ;38d2    32 d6 5c     2 . \ 
    ld (VAR_B_L),hl     ;38d5    22 d9 5c     " . \ 
    ld (VAR_C_L),de     ;38d8    ed 53 db 5c     . S . \ 
    call SEEKFILE01     ;38dc    cd 4c 2d     . L - 
    call #29D3          ;38df    cd d3 29     . . ) 
    call LOADPARM       ;38e2    cd dd 29     . . ) 
    jp FILELOAD01       ;38e5    c3 4d 2a     . M * 
    call ID_TYPE        ;38e8    cd 84 23     . . # 
    call SEEKFILE01     ;38eb    cd 4c 2d     . L - 
    jp ERASEFILE        ;38ee    c3 44 27     . D ' 

;------------------------------------------------------------------------------
; Subroutine: UnSTacK FILE
; Address: #38F1/14577
; Get filename string from calculator stack and seek it into directory.
; Output: Z flag=1 (file found),
;                0 (file not found);
;         C=number of file entry within directory;
;         (FILEPOS)=number of file entry within directory.
; Called by: DS_GOTO, DS_ERASE, LOADARG, FILEXIST.
;------------------------------------------------------------------------------
USTK_FILE               ;#38F1
    call GET_FNAME      ;#2CF2  Get filename from calculator stack.
    call ID_TYPE        ;#2384  Read disk configuration sector.
    jp SEEKFILE01       ;#2D4C  Seek file in the directory.

;------------------------------------------------------------------------------
; Subroutine: PRint FILENAMe
; Address: #38FA/14586
;　Print name and type of a file.
; Input: HL=directory entry address.
; Note: BC register pair is preserved.
; Called by: DS_CAT, OVERWRITE. 
;------------------------------------------------------------------------------
PR_FILENAM              ;#38FA
    push bc             ;       Stack BC.
    ld b,8              ;       Counter for 8 characters.

PR_FILENAM01            ;#38FD
    ld a,(hl)           ;       Get character from string and print.
    rst 16    
    inc hl              ;       Advance pointer to next character.
    djnz PR_FILENAM01   ;#38FD  Repeat until 8 characters are printed.
    ld a,"<"            ;       Print 'less than' character.
    rst 16    
    ld a,(hl)           ;       Print type of file ("B", "C", "D" or "#").
    rst 16    
    ld a,">"            ;       Print 'greater than' character.
    rst 16    
    pop bc              ;       Unstack BC.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: PRINT Numeric A
; Address: #390C/14604
; Print numeric value of A register.
; Called by: DS_CAT, RDWRSECT. 
;------------------------------------------------------------------------------
PRINTN_A                ;#390C
    ld c,a              ;       A=C to print C.
;------------------------------------------------------------------------------
; Subroutine: PRINT Numeric C
; Address: #390D/14605
; Print numeric value of C register. Actually this subroutine prints BC with 
;B=0.
; Called by: PRINTN_A, DS_CAT.
;------------------------------------------------------------------------------
PRINTN_C                ;#390D
    ld b,0              ;       B=0 to print BC.
    jp BAS_PRNTBC       ;#2E45  Print numeric value of BC.

;------------------------------------------------------------------------------
; BAS_PRNTBC01 (#3912/14610)
; Part of BAS_PRNTBC(#2E45/11845) subroutine. Call required BASIC routine.
;------------------------------------------------------------------------------
BAS_PRNTBC01            ;#3912
    call CALLBAS        ;#2E36  Call BASIC ROM routine (OUT-NUM-1).
    jp LOADCFGS         ;#392B  Jump to restore configuration sector at
                        ;       print buffer (BUFFER).

;------------------------------------------------------------------------------
; Subroutine: SAVE ConFiGuration Sector
; Address: #3918/14616
; Save data from configuration sector of disk (track 0, sector 8, normally
;stored at printer buffer) to a temporary place at DOS system variables NODISK 
;to FILETEMP.
; Note: AF and BC register pairs are preserved.
; Called by: PRNCHR01, BAS_PRNTBC.
;------------------------------------------------------------------------------
SAVECFGS                ;#3918
    push bc             ;       Stack BC and AF.
    push af    
    ld hl,BUFFER+224    ;       Source of data.
    ld bc,32            ;       Copy 32 bytes.
    ld de,NODISK        ;       Destination address (23761-23792/#5CD1-#5CF0).
    ldir                ;       Execute block copy.
    call IF1VSWP        ;#318C  Restore Interface 1 system variables.
    pop af              ;       Unstack BC and AF.
    pop bc    
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: LOAD ConFiGuration Sector
; Address: #392B/14635
; Recover data of configuration sector of disk (track 0, sector 8, normally
;stored at printer buffer) from a temporary place at DOS system variables 
;NODISK to FILETEMP.
; Preserved register: A.
; Called by: PRNCHR01, BAS_PRNTBC.
;------------------------------------------------------------------------------
LOADCFGS                ;#392B
    push af             ;       Save AF register.
    call IF1VSWP        ;#318C  Save Interface 1 system variables.
    ld hl,NODISK        ;       Origin (23761-23792/#5CD1-#5CF0).
    ld de,BUFFER+224    ;       Destination address.
    ld bc,32            ;       Copy 32 bytes.
    pop af              ;       Recover AF register.
    ldir                ;       Execute block copy.
    ret                 ;       End of subroutine.

;==============================================================================
; DOS Statement: 40 
; Address: #393C/14652
; Force DOS to acknowledge disk having 40 tracks.
; Syntax: 40 (actually 4 followed by any character)
;==============================================================================
DS_40                   ;#393C
    xor a               ;       Flag: #00=40 tracks. 

;------------------------------------------------------------------------------
; Common routine for DS_40 and DS_80
;------------------------------------------------------------------------------
DS_80_01                ;#393D
    ld (VAR_A_L),a      ;       Save flag temporarily into variable.
    call SYN_CHCK       ;#2E0E  Return if DOS is in syntax checking mode.
    call NOARG          ;#23AA  Raise syntax error condition if no argument is 
    jp z,ER_SYNTX       ;#2DB3  found; argument should be "0", but any 
                        ;       character is accepted.
    call FT_DSKTYPE     ;#3DBA  Fetch data of current disk type.
    ld a,(VAR_A_L)      ;       Get saved flag and put into DSKTYPE array 
    ld (hl),a           ;       element for current drive.
    jp DSTM_RET         ;#2170 

;==============================================================================
; DOS Statement: 80 
; Address: #3953/14675
; Force DOS to acknowledge disk having 80 tracks.
; Syntax: 80 (actually 8 followed by any character)
;==============================================================================
DS_80                   ;#3953
    ld a,#80            ;       Flag: #80=80 tracks.
    jr DS_80_01         ;#393D  Jump backward to continue this routine.

;==============================================================================
; Messages (#3957/14679-#39D9/14809)
;==============================================================================
M_ERROR                 ;#3957/14679
    defb #0D            ;       'Enter'
    defm "*ERROR*"
    defb #8D            ;       'Enter'+#80 (end of string marker)

M_NOSPACE               ;#3960/14688
    defb #0D            ;       'Enter'
    defm "No space"
    defb #8D            ;       'Enter'+#80 (end of string marker)

M_F_EXIST               ;#396A/14698
    defb #0D            ;       'Enter'
    defm "File exists"
    defb #8D            ;       'Enter'+#80 (end of string marker).

M_FREE                  ;#3977/14711
    defm " Free"
    defb #8D            ;       'Enter'+#80 (end of string marker).

M_RDONLY                ;#397D/14717
    defb #0D            ;       'Enter'
    defm "Read Onl"
    defb #F9            ;       "y"+#80, (end of string marker).

M_DSKERR                ;#3987/14727
    defb #0D            ;       'Enter'.
    defm "Disc Erro"
    defb #F2            ;       "r"+#80 (end of string marker).

M_RECOF                 ;#3992/14738
    defb #0D            ;       'Enter'
    defm "Rec.  O/"
    defb #C6            ;       "F"+#80 (end of string marker).

M_TITLE                 ;#399C/14748
    defm "Title:"
    defb #A0            ;       End of string marker, 'Space'+#80

M_RETRY                 ;#39A3/14755
    defb #0D            ;       'Enter'.
    defm "Retry,"
    defm "Abort,"
    defm "Ignore?"
    defb #00            ;       End of string marker.

M_TRK                   ;#39B8/14776
    defb #0D            ;       'Enter'
    defb "Trk"
    defb #A0            ;       End of string marker, 'Space'+#80

M_SEC                   ;#39BD/14781
    defm " sec"
    defb #A0            ;       End of string marker, 'Space'+#80

M_DELFILE               ;#39C2/14786
    defm " Del. File"
    defb #8D            ;       'Enter'+#80 (end of string marker)

M_NOFILE                ;#39CD/14797
    defb #0D            ;       'Enter'
    defm "No"

M_FILE                  ;#39D0/14800
    defm " File(s)"
    defb #8D            ;       'Enter'+#80 (end of string marker)
    defb #00            ;       Final end marker.

;=============================================================================
; NMI01 (#39DA/14810)
; This is the main non-maskable interrupt service routine (NMI, started from
; #0066/102).
;=============================================================================
NMI01                   ;#39DA
; Save contents os Z80 registers onto stack.
    push af             ;       Save contents of AF, BC, DE, and HL main 
    push bc             ;       register pairs onto stack.
    push de    
    push hl    
    push ix             ;       Save IX and IY special registers.
    push iy
    exx                 ;       Save BC', DE' and HL' alternate register pairs.
    push bc    
    push de    
    push hl    
    ex af,af'           ;       Save AF' alternate register pair.
    push af    
    ld a,i              ;       Save I special register and IFF2 status (copied
    push af             ;       into P/V flag).
    ld a,r              ;       Save R special register and IFF2 status.
    push af    
    ld hl,0             ;       Put SP value into HL.
    add hl,sp    
    push hl             ;       Save SP value.
; Activate drive A, save part of RAM in disk and prepare workspace in RAM.
    ld a,%00111100      ;       Initialize port 255: drive A, side 0, double 
    out (255),a         ;       density and DOS ROM enabled.
    call NMI_RESTORE    ;#3BED  Place head onto track 0.
    call LONGDELAY      ;#3E3D  Wait for head stabilization.
    ld de,10            ;       E=10, disk sector where data wil be written.
    ld hl,VID_RAM       ;       Save RAM from adress 16384.
    push hl             ;       Save pointer onto stack.
    call NMI_WRSEC      ;       Save 256 bytes of RAM into track 0/sector 10.
    pop hl              ;       Restore pointer and save again.
    push hl
    ld de,8             ;       Read disk configuration sector (track 0/
    call NMI_RDSEC      ;#3BA7  sector 8) and write to RAM starting from 
    ld hl,VID_RAM+CS_FREET ;    address 16384.
    ld a,(hl)           ;       Take first free track of disk and add to it 12
    add a,12            ;       (12 tracks store 49152 bytes, size of all RAM
    ld (hl),a           ;       of a 48K Spectrum).
    inc hl              ;       HL points to CS_DTYPE.
    ld a,(hl)           ;       Fetch CS_DTYPE value and write to KSTATE.
    ld (KSTATE),a
    inc hl              ;       HL points to CS_NFILE.
    ld a,(hl)           ;       Jump ahead and skip next instructions if number 
    or a                ;       of files in the disk is not 0. Note: if some 
    jr nz,NMI02         ;#3A35  files already exist in the disk, CS_NFILE and 
                        ;       CS_NFREE will not be updated.
    inc (hl)            ;       Increment number of files (1 file).
    inc hl              ;       HL points to CS_NFREE.
    ld e,(hl)           ;       DE=number of free sectors.
    inc hl    
    ld d,(hl)    
    ld hl,#FF40         ;       HL=-192. Subtract 192 (49152 bytes) from number 
    add hl,de           ;       of free sectors and update CS_NFREE.
    ld (VID_RAM+CS_NFREE),hl
    ld hl,VID_RAM       ;       Save new configuration sector stored from 
    ld de,8             ;       address 16384 to sector 8 of disk (head is 
    call NMI_WRSEC      ;       already on track 0).

NMI02                   ;#3A35
; Save all 48K RAM and prepare directory entry.
    pop hl              ;       HL=16384.
    ld de,10            ;       Read 256 bytes of RAM saved into sector 10 and
    call NMI_RDSEC      ;#3BA7  restore previous state of RAM at 16384-16639.
    call RAMDUMP        ;#3A87  Save 49152 bytes of RAM into 192 sectors.
    ld a,%00111100      ;       Select side 0 of disk (bit 4=1).
    out (255),a
    call NMI_RESTORE    ;#3BED  Move head to track 0.
    ld hl,VID_RAM       ;       Read first directory sector and write to start 
    ld de,0             ;       of RAM. The first directory entry will be remade 
    call NMI_RDSEC      ;#3BA7  and overwritten.
    ld (hl),"@"         ;       First byte of filename will be "@".
    inc hl              ;       Advance pointer to second byte of filename.    
    ld b,7              ;       Label has more 7 characters.

NMI03                   ;#3A54
    ld (hl)," "         ;       Next characters will be space (#20/32).
    inc hl              ;       Increment RAM pointer.
    djnz NMI03          ;#3A54  Repeat until all characters is " ".
    ld (hl),"C"         ;       Filetype will be "C" (CODE).
    pop hl              ;       Fetch old SP value from stack.
    ld (VID_RAM+9),hl   ;       Save into file parameter 1 field.
    ld hl,#0100         ;       H=track 1 (first file data track), L=sector 0.
    ld (VID_RAM+14),hl  ;       Save into file sector/track fields.
    ld a,192            ;       Save file size value (192 tracks) into file
    ld (VID_RAM+13),a   ;       size field.
    ld hl,VID_RAM       ;       Start address of RAM to be saved.
    ld de,#0000         ;       D=track 0, E=sector 0.
    call NMI_WRSEC      ;       Write directory entry to disk.
    ld hl,VID_RAM       ;       Start address of RAM to be restored.
    ld de,#0100         ;       D=track 1, E=sector 0.
    ld c,1              ;       Move head to track 1, where first bytes of RAM 
    call NMI_SEEKL      ;#3BC5  has been saved.
    call NMI_RDSEC      ;#3BA7  Read sector and restore RAM.
    ld a,%00111100      ;       Save state of port 255 onto stack.
    push af    
    jp REG_REC          ;       Jump to recover all register values.
  
;------------------------------------------------------------------------------
; Subroutine: RAM DUMP 
; Address: #3A87/14983
; Dump all RAM contents of computer to disk (49152 bytes, 192 sector or 12 
;tracks.
; Called by: NMI02.
;------------------------------------------------------------------------------
RAMDUMP                 ;#3A87
    call NMI_RESTORE    ;#3BED  Move head onto track 0.
    ld c,1              ;       Move head onto track 1.
    call NMI_SEEKL      ;#3BC5
    ld hl,VID_RAM       ;       HL= address of computer RAM start.
    ld de,#0100         ;       D=track 1, E=sector 0.
    ld b,192            ;       Counter of sectors, 192 sectors (49152 bytes).

RAMDUMP01               ;#3A97
    push bc             ;       Stack counter and track/sector ID.
    push de
    call NMI_WRSEC      ;       Write one sector to disk.
    ld de,256           ;       Update pointer, advancing 256 bytes.
    add hl,de    
    pop de              ;       Unstack track/sector ID.
    inc e               ;       Increment sector number.
    ld a,e              ;       Skip next instructions if sector ID isn't 16.
    cp 16
    jr nz,RAMDUMP02
    ld e,0              ;       Sector number reached max. value (16), so it's 
    inc d               ;       reset to 0 and track number is incremented.
    ld c,d              ;       Assign logical track number to C register.
    call NMI_SEEKL      ;#3BC5  Move head to track number C.

RAMDUMP02               ;#3AAE
    pop bc              ;       Unstack counter.
    djnz RAMDUMP01      ;       Decrement B and repeat for all 192 sectors.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: NMI WRITE SECTOR 
; Address: #3AB2/15026
; Short version of WRITESECTOR subroutine. Write 256 bytes of RAM content into
;a disk sector. Drive head must be positioned onto the proper track.
; Input:  HL=start address of block of 256 bytes to save;
;         E=logical sector ID where block will be saved.
; Called by: NMI01, RAMDUMP. 
;------------------------------------------------------------------------------
NMI_WRSEC               ;#3AB2
    ld a,e              ;       Copy number of sector to A (range is 0-15).
    inc a               ;       Change logical sector to physical sector (range 
    out (95),a          ;       is 1-16) and send value to FDC sector register.
    push hl             ;       Stack address.
    ld d,10             ;       Counter for 10 attempts.
    push de             ;       Stack counter and sector ID.

NMI_WRSEC01             ;#3ABA
    ld c,127            ;       Port address of FDC sector register.
    ld a,#A0            ;       Code of WRITE SECTOR command.
    out (31),a          ;       Send command to FDC.
    call FDC_WDATA02    ;#3F60  Send 256 bytes to FDC.
    pop de              ;       Unstack counter and sector ID.
    pop hl              ;       Unstack address.
    in a,(31)           ;       Read status register of FDC.
    and %01111111       ;       Bits 0-6 is 0 if no error.
    ret z               ;       Return in no error ocurred.
    dec d               ;       An error ocurred, decrement counter.
    push hl             ;       Stack address.
    push de             ;       Stack counter and sector ID.
    jr nz,NMI_WRSEC01   ;       Retry writing if counter is not 0.
    halt                ;       Freeze computer after 10 unsuccessful attempts 
                        ;       (HALT with interrupt disabled).
;==============================================================================
; DOS Statement: GOTO 
; Address: 15056/#3AD0
; Load and run a CODE file saved by Magic Button (NMI at #66/102).
; Syntax:   GOTO <n$>CODE   
;   (n$=filename)
; Note: if first character of filename is "$" (dollar sign), interrupt mode 2
;(IM2) will be selected. Some programs need this mode to work properly. There
;is no automatic way to detect interrupt mode by NMI routine, thus it must be 
;set manually.
;==============================================================================
DS_GOTO                 ;#3AD0
    call GET1ARG_S      ;#2E7C  Get filename from command line.
    call SYN_CHCK       ;#2E0E  Return if DOS is in syntax checking mode.
    call FIND_FTYPE     ;#24F1  Get file type.
    call USTK_FILE      ;#38F1  Search filename in the directory.
    jp nz,ER_NOFILE     ;#2358  Jump to error routine if file does not exist.
    call GETENTRY       ;#27AE  Get directory entry data from disk.
    ld a,(FILENAME)     ;       Fetch first character of filename.
    cp "$"              ;       Jump forward if not dollar sign and use default
    jr nz,DS_GOTO01     ;#3AEB  Interrupt Mode 1.
    im 2                ;       Otherwise, use Interrupt Mode 2.

DS_GOTO01               ;#3AEB
; Video RAM area (VID_RAM) will be used as a temporary workspace.
    ld sp,VID_RAM+240   ;       Temporary stack point position.
    call FT_DSKTYPE     ;#3DBA  Fetch data of current disk type.
    ld (VID_RAM+16),a   ;       Store disk type into video RAM.
    ld a,(PORT255)      ;       Store last value sent to port 255 into video 
    ld (VID_RAM+17),a   ;       RAM.
    ld hl,(FILEPARM1)   ;       Fetch SP value and push onto stack.
    push hl    
    ld de,(FILESECT)    ;       D=start track ID, E=start sector ID.
    push de             ;       Stack track and sector ID.
    inc e               ;       Increment sector ID.
    ld a,e    
    cp 16
    jr nz,DS_GOTO02     ;#3B0C  Jump forward if sector number is not 16;
    ld e,0              ;       otherwise, reset sector ID and increment 
    inc d               ;       track ID.

DS_GOTO02               ;#3B0C
    ld c,d              ;       C=logical track number.
    call GOTO_SIDE0     ;#3B93  Select side 0 of disk.
    ld a,(VID_RAM+16)   ;       A=disk type.
    and %00000010       ;       Select side 1 if disk has 2 sides and logical 
    call nz,GOTO_SIDE1  ;#3B9B  track ID is odd.
    ld a,c              ;       A=physical track number.
    call NMI_SEEKA      ;       Move disk head onto this track.
    ld hl,VID_RAM+256   ;       Set pointer 256 bytes ahead of RAM start.
    ld b,191            ;       Counter of 191 sectors.

DS_GOTO03               ;#3B21
; This loop will read all RAM except the first 256 bytes, used as workspace.
    push bc             ;       Stack sector counter.
    push de             ;       Stack track and sector ID.
    call NMI_RDSEC      ;#3BA7  Read sector from disk and write to RAM.
    ld de,256           ;       Update pointer advancing 256 bytes.
    add hl,de
    pop de              ;       Unstack track and sector ID.
    inc e               ;       Increment sector ID.
    ld a,e
    cp 16               ;       Jump forward if last track (15) is not 
    jr nz,DS_GOTO04     ;#3B44  exceeded.
    ld e,0              ;       Otherwise, reset sector ID and increment track
    inc d               ;       ID.
    ld c,d    
    call GOTO_SIDE0     ;#3B93  Select side 0 of disk.
    ld a,(VID_RAM+16)   ;       A=disk type.
    and %00000010       ;       Select side 1 if disk has 2 sides and logical 
    call nz,GOTO_SIDE1  ;#3B9B  track ID is odd.
    ld a,c              ;       A=physical track number.
    call NMI_SEEKA      ;       Move disk head onto that track.

DS_GOTO04               ;#3B44
    pop bc              ;       Unstack sector counter.
    djnz DS_GOTO03      ;#3B21  Repeat until all 191 sectors were read.
    pop de              ;       Restore sector/track ID from stack.
    pop hl              ;       Unstack value and assign to SP.
    ld sp,hl
    ld a,(VID_RAM+17)   ;       Fetch port 255 status and save onto stack.
    push af             ;       Stack port 255 status.
    ld c,d              ;       C=logical track number.
    call GOTO_SIDE0     ;#3B93  Select track 0.
    ld a,(VID_RAM+16)   ;       A=disk type.
    and %00000010       ;       Select side 1 if disk has 2 sides and logical 
    call nz,GOTO_SIDE1  ;#3B9B  track number is odd.
    ld a,c              ;       A=physical track number.
    call NMI_SEEKA      ;       Move disk head onto that track.
    ld hl,VID_RAM       ;       Read the first sector of file into start of 
    call NMI_RDSEC      ;#3BA7  RAM.
;------------------------------------------------------------------------------
; REGisters RECover 
; Address: #3B64/15204
; Recover all Z80 registers, IFF1 and IFF2 values at end of NMI routine (Magic 
;Button) or GOTO statement.
;------------------------------------------------------------------------------
REG_REC                 ;#3B64
    pop af              ;       Store temporarily last byte sent to port 255 
    ex af,af'           ;       into alternate register A'.
    pop af              ;       Recover R.
    ld r,a
    pop af              ;       Recover I and IFF2.
    ld i,a
    jp po,REG_REC01     ;#3B81  Jump forward if IFF2=0.
    pop af              ;       Recover alternate registers: A', B', C', D', 
    pop hl              ;       E', F', H' and L'.
    pop de    
    pop bc    
    exx    
    ex af,af'           ;       A contains last byte sent to port 255.
    pop iy              ;       Recover special registers IX and IY.
    pop ix
    pop hl              ;       Recover general registers B, C, D, E, H and L.
    pop de    
    pop bc    
    or %10000000        ;       Bit 7 of port 255 will be 1 to enable BASIC 
                        ;       ROM.
    jp REGREC_EI        ;#3B88  Jump forward to the area watched by Beta
                        ;       interface. Interrupts will be enabled.
;------------------------------------------------------------------------------
; REG_REC01 (#3B81/15204). Finish DS_GOTO or NMI routine with interrupts 
;disabled.
;------------------------------------------------------------------------------
REG_REC01               ;#3B81
    pop af              ;       Recover alternate registers: A', B', C', D', 
    pop hl              ;       E', F', H' and L'.
    pop de    
    pop bc    
    exx    
    ex af,af'           ;       A contains last byte sent to port 255.
    pop iy              ;       Recover special registers IX and IY.
    pop ix
    pop hl              ;       Recover general registers B, C, D, E, H and L.
    pop de    
    pop bc    
    or %10000000        ;       Bit 7 of port 255 will be 1 to enable BASIC 
                        ;       ROM.
    jp REGREC_DI        ;#3C90  Jump forward to the area watched by Beta
                        ;       interface. Interrupts will not be enabled.

;------------------------------------------------------------------------------
; Subroutine: GOTO SIDE 0
; Address: #3B93/15251
; Select side 0 of disk.
; Called by: DS_GOTO.
;------------------------------------------------------------------------------
GOTO_SIDE0              ;#3B93
    ld a,(VID_RAM+17)   ; Take last value sent to port 255 and raise bit 4
    or %00111100        ;to select side 0.

GOTO_P255               ;#3B98
    out (255),a         ; Send value to port 255.
    ret                 ; End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: GOTO SIDE 1
; Address: #3B9B/15259
; Select side 1 of disk if logical track number is odd.
; Input:  C=phyical track number.
; Output: C=logical track number.
; Called by: DS_GOTO
;------------------------------------------------------------------------------
GOTO_SIDE1              ;#3B9B
    ld a,c              ;       A=physical track number.
    or a                ;       C flag=0.
    rra                 ;       A/2 is logical track number.
    ld c,a              ;       C=logical track number.
    ret nc              ;       Return if track number is even.
    ld a,(VID_RAM+17)   ;       Take last value sent to port 255 and reset 
    and %01101111       ;       bit 4 to select side 1.
    jr GOTO_P255        ;#3B98  Jump bakcward to write to port 255.

;------------------------------------------------------------------------------
; NMI READ SECTOR 
; Address: #3BA7/15271
; Short version of READSECTOR subroutine. Read 256 bytes of RAM content into
;a disk sector. Drive head must be positioned onto proper track.
; Input:  HL=start address to where block of 256 bytes will be saved;
;         E=logical sector ID to be read.
; Called by: NMI01, DS_GOTO.
;------------------------------------------------------------------------------
NMI_RDSEC               ;#3BA7
    ld a,e              ;       A=logical sector ID (range 0-15).
    inc a               ;       Change logical sector to physical sector (range 
    out (95),a          ;       1-16) and send value to FDC sector register .
    push hl             ;       Stack address.
    ld d,10             ;       Counter for 10 retries if error detected.
    push de             ;       Stack sector and counter.

NMI_RDSEC01             ;#3BAF
    ld c,127            ;       Port address of FDC sector register.
    ld a,#80            ;       Code of READ SECTOR command.
    out (31),a          ;       Send command to FDC.
    call FDC_RDATA02    ;#3F7B  Read 256 bytes from FDC.
    pop de              ;       Unstack sector and counter.
    pop hl              ;       Unstack address.
    in a,(31)           ;       Read status register of FDC.
    and %01111111       ;       Bits 0-6 will be 0 if no error.
    ret z               ;       Return in no error detected.
    dec d               ;       An error ocurred, decrement counter.
    push hl             ;       Stack address and counter.
    push de    
    jr nz,NMI_RDSEC01   ;#3BAF  Retry sector writing if counter is not 0.
    halt                ;       Freeze computer after 10 unsuccessful attempts 
                        ;       (HALT with interrupt disabled).
   
;------------------------------------------------------------------------------
; NMI SEEK Logical 
; Address: #3BC5/15301
; Shorter version of TRACK_LA. Single face disk has concentric tracks numbered 
;sequentially starting from 0 and data are written in that order. Double face 
;disk has data being written in alternating order, into side 0 for even tracks 
;and into side 1 for odd tracks. This subroutine position disk head on physical
;track number calculated from logical track number given in C register.
; Input: C=logical track number.
; Called by: NMI02, RAMDUMP.
;------------------------------------------------------------------------------
NMI_SEEKL               ;#3BC5
    ld a,%00111100      ;       Select side 0 (bit 4=1). Also select drive A 
    out (255),a         ;       and double density disk.
    ld a,(KSTATE)       ;       Fetch disk type saved by NMI01 routine.
    and %00001000       ;       Skip next instructions if single density (types 
    jr nz,NMI_SEEKL01   ;#3BDA  22/#18 or 23/#19).
    ld a,c              ;       A=logical track  
    or a                ;       Reset C flag.
    rra                 ;       A=A/2, remainder of division is in C flag.
    ld c,a              ;       C=physical track.
    jr nc,NMI_SEEKL01   ;#3BDA  Skip next instructions if side 0.
    ld a,%00101100      ;       Select side 1 (bit 4=0).
    out (255),a

NMI_SEEKL01             ;#3BDA
    ld a,c              ;       A=physical track, continue through NMI_SEEKA.

;------------------------------------------------------------------------------
; NMI SEEK A 
; Address: 15323/#3BDB
; Short version of TRACK_PA subroutine. Position disk head onto physical track 
;A.
; Input: A=number of physical track of disk
; Called by: NMI_SEEKL, DS_GOTO.
;------------------------------------------------------------------------------
NMI_SEEKA               ;#3BDB
    out (127),a         ;       Send track ID to FDC data register.
    ld a,#1B            ;       Code of SEEK command of FDC, position head onto
                        ;       track pointed by FDC Track register.
NMI_REST01              ;#3BDF
; NMI_RESTORE subroutine continues here.
    out (31),a          ;       Send commando to FDC.

WAITINTRQ               ;#3BE1
    in a,(255)          ;       Read port 255.
    and %10000000       ;       Repeat port reading until bit 7 returns 1 
                        ;       (INTRQ=1, i.e. FDC command was finished).
    jr z,WAITINTRQ      ;#3BE1 
    push bc             ;       Save BC onto stack.
    call DELAY          ;#3DA6  Wait 0.15 s.
    pop bc              ;       Restore BC.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; NMI RESTORE 
; Address: #3BED/15341
; Short version of RESTORE subroutine. Position head onto track 0.
; Called by: NMI01, RAMDUMP.
;------------------------------------------------------------------------------
NMI_RESTORE             ;#3BED
    ld a,#0B            ;       Code of FDC command RESTORE
    jr NMI_REST01       ;#3BDF  Jump backward.

;------------------------------------------------------------------------------
; Unused bytes and codes (#3BF1/15345-#3BFF/15359)
;------------------------------------------------------------------------------
    defb #FF,#FF,#FF,#FF
    defb #FF,#FF,#FF,#FF
    defb #FF
   
    jp IF1VSWP          ;#318C
    jp #380F

;##############################################################################
; Start of area watched by Beta disk interface
; --------------------------------------------
; During normal operation of BASIC monitor, the region at 15360-15615 (#3C00-
;#3CFF) are watched by the disk interface. Any attempt of access here will
;show ;contents of DOS ROM instead of BASIC (unless this feature is disabled - 
;see Port 252 in 'I/O ports used by CAS interface'). This small area provides
;interfacing between DOS and BASIC.
;##############################################################################

;==============================================================================
; DOS Command Line Interface
; Address: #3C00/15360
; In CLI mode, DOS awaits for a line being typed by the user. The editing is
;finished when 'Enter' key is pressed and the line is interpreted by DOS to
;be executed. This entry point is used to access DOS CLI from BASIC, typing
;'RANDOMIZE USR 15360'. Conversely, 'RETURN' DOS statement force exit from CLI 
;mode and BASIC monitor take control of computer.
;==============================================================================
DOS_CLI                 ;#3C00
    jp DOS_CLI01        ;#3C49  Jump forward to the main routine.

;==============================================================================
; DOS BASIC interface
; Address: #3C03/15363
; From BASIC monitor, DOS interpreter is invoked by: 
;<BASIC statement> USR 15363 : REM : <DOS statement>
;(RANDOMIZE is the most common BASIC statement employed here, but any statement
;that accepts numeric argument like 'LET error=', for example, is acceptable).
;==============================================================================
DOS_BASIC               ;#3C03
    jp DOS_BASIC01      ;#3C30  Jump forward to the main routine.

;------------------------------------------------------------------------------
; Address: #3C06/15366
; Entry point to routine that select DOS ROM.
;------------------------------------------------------------------------------
;#3C06
    jp ROMBETA_R        ;#3C68 

;==============================================================================
; Routine: CH_INPUT
; Address: #3C09/15369
; Channel "D" input routine. When a BASIC statement try to read from stream
;file (INPUT# or INKEY$#), this routine is called. In read access mode
;sequential file, each character read from disk behaves like a key press. Thus,
;INKEY$# returns one character, whereas INPUT# expects a sequence of characters
;ending with 'enter' (#0D/13) to be evaluated and assigned to a variable. File
;in random access mode is more complicated because INPUT# gives to stream the
;record ID, before accepting characters from disk.
; Output: A=code of character returned by stream file;
;         C flag=1.
;==============================================================================
CH_INPUT                ;#3C09
    call ROMBETA_R      ;#3C68  Page in the DOS ROM.
    jp CH_INP01         ;#368B  Jump backward to the main routine.

;==============================================================================
; Routine: CH_OUTPUT
; Address: #3C0F/15375
; Channel "D" output routine. When BASIC is sending a character to stream file,
;this routine is called. PRINT# is the most common way to send character to a
;stream, but another statements can be used like LIST#, LPRINT#, LLIST# and 
;even INPUT# can send characters to stream. Stream opened as write mode 
;sequential file accepts characters. Thus, strings are written as sequences of
;characters and numbers or numeric expressions are evaluated and written in
;decimal numeric format. Random access mode file is more complicated, even to
;perform INPUT operation, a record number must be sent beforehand to stream 
;(e.g. 'INPUT #4;(12),a$'). In this case, first a record number is sent through
;CH_OUTPUT routine, then input is performed by CH_INPUT routine. Output routine
;evaluate record number expression when stream file is in random mode.
; Input:  A=code of character being sent to stream.
;==============================================================================
CH_OUTPUT               ;#3C0F
    call ROMBETA_R      ;#3C68  Page in the DOS ROM.
    jp CH_OUT01         ;#34DB  Jump backward to the main routine.

;------------------------------------------------------------------------------
; Subroutine: DOS ERROR
; Address: #3C15/15381
; Return address from error condition raised during DOS operation.
; Called by: DEF_ERRSP.
;------------------------------------------------------------------------------
DOSERROR                ;#3C15
    ld hl,(OLDSP)       ;       Restore old value of Z80 stack pointer.
    dec hl    
    dec hl    
    ld sp,hl    
    call ROMBETA_R      ;#3C68  Assign HL=ROM_BETA and select DOS ROM.
    jp DOSERROR01       ;#2DC8  Jump backward.

;------------------------------------------------------------------------------
; EXEC_BAS02 (#3C21/15393)
; Part of EXEC_BAS (#20F1/8433) routine.
;------------------------------------------------------------------------------
EXEC_BAS02              ;#3C21
    ld sp,(ERR_SP)      ;       Stack point is pointing to stack element with 
                        ;       return address after an error.
    ld a,(LDPKEXEC)     ;       Fetch flag.
    or a                ;       Execute next jump only if flag=0 (run BASIC).
    jp z,#1B76          ;       Jump to STMT-RET routine of BASIC ROM, give 
                        ;       control to BASIC monitor in program interpreter
                        ;       mode, and start program.
    pop hl              ;       Remove return address from stack.
    jp #12CF            ;       Jump to MAIN-3 routine of BASIC ROM. System 
                        ;       control is given to BASIC monitor in line 
                        ;       editor mode.

;------------------------------------------------------------------------------
; DOS_BASIC01 (#3C30/15408)
; DOS_BASIC (#3C03/15363) continues here.
;------------------------------------------------------------------------------
DOS_BASIC01             ;#3C30
    call INITDOS        ;#3C37  Initialize DOS variables and assign HL=
    push hl             ;       DOS_BASIC. This address is saved onto stack.
    jp DOS_BASIC02      ;#2124  Jump backward to the rest of routine.

;------------------------------------------------------------------------------
; Subroutine: INIT DOS
; Address: #3C37/15415
; Initialize DOS variables if necessary.
; Output: HL=ROM_BASIC.
; Called by: DOS_CLI01, DOS_BASIC01.
;------------------------------------------------------------------------------
INITDOS                 ;#3C37
    ld a,(FLAGBUFF)     ;       Check if flag is #AA.
    cp #AA
    call nz,INITVARS    ;#3CD6  Initialize DOS variable if it is not.
    jr ROMBETA_R        ;#3C68  Jump to select DOS ROM (HL=ROM_BASIC).

;------------------------------------------------------------------------------
; RESET09 (#3C41/15425)
; Continuation of RESET08 (#2069/8297). Initialization of BASIC (RESET) ends 
;here and execution go through DOS_CLI01.  
;------------------------------------------------------------------------------
RESET09                 ;#3C41
    ld a,#FF            ;       Initialize status of port 255 with all bits 
    ld (PORT255),a      ;       high.
    call ROM_BASIC      ;#3C7C  Enable BASIC ROM but DOS ROM is still visible 
                        ;       at 15360-15615 (#3C00-#3CFF) range.
;------------------------------------------------------------------------------
; DOS_CLI01 (#3C49/15433)
; Main DOS CLI routine starts here.
;------------------------------------------------------------------------------
DOS_CLI01               ;#3C49
    call INITDOS        ;#3C37  Initialize system variables if neccessary.
    push hl             ;       Stack ROM_BASIC as return address.
    jp DOS_CLI02        ;#21DC  Jump backwards.

;------------------------------------------------------------------------------
; Subroutine: CALL BASic 1
; Address: #3C50/15440
; Call a subroutine from BASIC ROM. Stack must contain address of the BASIC
;subroutine, under return address of this subroutine itself. 
; Called by: DS_RUN, CALLBAS, CALLBASHL.
;------------------------------------------------------------------------------
CALLBAS1                ;#3C50
    rst 32              ;       Save HL.
    ld (DETEMP),de      ;       Save DE.
    pop de              ;       Get return address.
    pop hl              ;       Get BASIC routine address.
    push de             ;       Put return address onto stack.
    call ROM_BASIC      ;#3C7C  Enable BASIC ROM.
    ld de,ROM_BETA      ;#3C6B  Put ROM_BETA address onto stack, so DOS ROM is
    push de             ;       enabled after returning from BASIC subroutine.
    push hl             ;       Stack address of BASIC routine to be executed.
    ld de,(DETEMP)      ;       Restore DE and HL.
    ld hl,(HLTEMP)
    ret                 ;       Jump to the BASIC routine.

;------------------------------------------------------------------------------
; Subroutine: ROM_BETA
; Address: #3C6B/15467
; Select DOS ROM, giving acess to all DOS routines.
; Output: HL=ROM_BASIC;
;         IFF1=0.
; Note: All registers but HL are preserved.
; Called by: CH_INPUT, CH_OUTPUT, DOSERROR, DOS_CLI01, LDDR_BAS, LDIR_BAS, 
;CALLBAS1.
;------------------------------------------------------------------------------
ROMBETA_R               ;#3C68
; In this entry point, address of ROM_BASIC routine is held by HL to be used as 
;return address.
   ld hl,ROM_BASIC      ;#3C7C  

ROM_BETA                ;#3C6B
    di                  ;       Disable makable interrupts.
    push af             ;       Save AF contents onto stack.
    call IO_OFF         ;#3C97  Enable disk interface I/O ports.
    ld a,(PORT255)      ;       Fetch last value sent to port 255.
    and %01111111       ;       Lower bit 7 to enable DOS ROM.
    ld (PORT255),a      ;       Update system variable.
    out (255),a         ;       Send value to port 255.
    pop af              ;       Restore AF pair contents.
    ret                 ;       Finish subroutine with interrupt disabled.

;------------------------------------------------------------------------------
; Subroutine: ROM_BASIC
; Address: #3C7C/15484
; Select BASIC ROM. DOS routines at 15360-15615 (#3C00-#3CFF) area are still 
;accessible.
; Output: IFF1=1.
; Note: All registers are preserved.
; Called by: BASDOSRET, RESET09, CALLBAS1, ROMBETA_R.
;------------------------------------------------------------------------------
ROM_BASIC               ;#3C7C
    push af             ;       AF register pair is saved onto stack.
    call IO_OFF         ;#3C97  Enable CAS interface I/O ports.
    ld a,(PORT255)      ;       Fetch last value OUTed to port 255.
    or %10000000        ;       Raise bit 7 to enable BASIC ROM.
    ld (PORT255),a      ;       Update system variable.

;------------------------------------------------------------------------------
; REGREC_EI (#3C88/15496)
; Finish NMI/DS_GOTO routines with maskable interrupt enabled.
;------------------------------------------------------------------------------
REGREC_EI               ;#3C88
    out (255),a         ;       Write value to port 255.
    call IO_ON          ;#3C9D  Disable CAS interface I/O ports.
    pop af              ;       Restore AF pair contents.
    ei                  ;       Enable maskable interrupts.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; REGREC_DI (#3C90/15504)
; Finish NMI/DS_GOTO routines with maskable interrupt disabled.
;------------------------------------------------------------------------------
REGREC_DI               ;#3C90
    out (255),a         ;       Write to port 255.
    call IO_ON          ;#3C9D  Disable CAS interface I/O ports.
    pop af              ;       Restore AF pair contents.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: I/O OFF
; Address: #3C97/15511
; Disable I/O with peripheral attached to disk interface rear connector but
;enable I/O with CAS interface. Thus, DOS operations don't mess with another
;peripherals. Also keep CAS ROM visible at #3C00/15360-#3CFF/15615 area (if 
;not, this subroutine will crash).
; Called by: ROM_BETA, ROM_BASIC, ROMBETA_Q, ROMBAS_Q
;------------------------------------------------------------------------------
IO_OFF                  ;#3C97
    call F_BORDC        ;#3CAF  Fetch current border colour (bits 3-7 are low).
    out (252),a         ;       Write value to port 252.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: I/O ON
; Address: #3C9D/15517
; Enable I/O with peripheral attached to disk interface rear connector but
;inihibit I/O with CAS interface. Thus, CAS circuitry remains silent during 
;another peripheral I/O operation. Also keep CAS ROM visible at 15360-15615 
;(#3C00-#3CFF) area (if not, this subroutine would crash) .
; Called by: REGREC_EI, REGREC_DI. 
;------------------------------------------------------------------------------
IO_ON                   ;#3C9D
    call F_BORDC        ;#3CAF  Fetch current border colour (bits 3-7 are low).
    or %10000000        ;       Raise bit 7.
    out (252),a         ;       Write value to port 252.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: Wait Key
; Address: #3CA5/15525
; Wait until a key is pressed. The maskable interrupt must be enabled; if not,
;this subroutine will wait forever.
; Called by: READKEY. 
;------------------------------------------------------------------------------
WAITKEY                 ;#3CA5
    ld hl,FLAGS         ;       HL points to system variable.

WAITKEY01               ;#3CA8
    bit 5,(hl)          ;       Test bit 5.
    jr z,WAITKEY01      ;#3CA8  Retry while bit 5 is low (no keypress).
    res 5,(hl)          ;       Reset bit 5 to signal 'ready to further 
    ret                 ;       keyboard scan' and finish subroutine.
 
;------------------------------------------------------------------------------
; Subroutine: Fetch BORDer ColouR
; Address: #3CAF/15535
; Fetch PAPER colour value from the current lower screen line colour  
;attributes. This value is used for output operation involving even port
;address without change of border colour. 
; A=0-7 (0-black; 1-blue; 2-red; 3-magenta; 4-green; 5-cyan; 6-yellow; 
;        7-white)
; Called by: IO_OFF, IO_ON.
;------------------------------------------------------------------------------
F_BORDC                 ;#3CAF
    ld a,(BORDCR)       ;       Get current attribute values (%FBPPPIII).
    and %00111000       ;       Mask out unnecessary bits (%00PPP000).
    rrca                ;       Shift bits three times to right (%00000PPP).
    rrca
    rrca
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: ROMBETA_Q
; Address: #3CB8/15544
; Short and quick version of ROM_BETA. Enable full access to DOS ROM and
;disable BASIC ROM. Doesn't update PORT255 system variable and AF register
;contents are destroyed.
; Called by: INITVARS.
;------------------------------------------------------------------------------
ROMBETA_Q               ;#3CB8
    di                  ;       Disable interrupts.
    call IO_OFF         ;#3C97  Enable CAS interface I/O ports.
    ld a,%01111111      ;       Bit 7 is lowered to enable DOS ROM.
    jr ROMBETA_Q1       ;#3CC5  Write value into port 255.

;------------------------------------------------------------------------------
; Subroutine: ROMBAS_Q
; Address: #3CC0/15552
; Short and quick version of ROM_BASIC. Disable access to DOS ROM, except at
;15360-15615 (#3C00-#3CFF) area, and enable BASIC ROM.
; Called by: LDDR_BAS, LDIR_BAS
;------------------------------------------------------------------------------
ROMBAS_Q                ;#3CC0
    call IO_OFF         ;#3C97  Enable CAS interface I/O ports.
    ld a,%11111111      ;       Bit 7 is raised to disable DOS ROM.

;------------------------------------------------------------------------------
; This part is common to ROMBETA_Q and ROMBASIC_Q.
;------------------------------------------------------------------------------
ROMBETA_Q1              ;#3CC5
    out (255),a         ;       Write value to port 255.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: LDDR_BAS
; Address: #3CC8/15560
; Copy data from BASIC ROM to RAM. Address are scanned downwards (LDDR).
; Called by: RESET07.
;------------------------------------------------------------------------------
LDDR_BAS                ;#3CC8
    call ROMBAS_Q       ;#3CC0  Page in BASIC ROM.
    lddr                ;       Copy data from ROM.
    jr ROM_BETA         ;#3C6B  Finish, paging in DOS ROM.

;------------------------------------------------------------------------------
; Subroutine: LDIR_BAS
; Address: #3CCF/15567
; Copy data from BASIC ROM to RAM. Address are scanned upwards (LDIR).
; Called by: RESET08.
;------------------------------------------------------------------------------
LDIR_BAS                ;#3CCF
    call ROMBAS_Q       ;#3CC0  Page in BASIC ROM.
    ldir                ;       Copy data from ROM.
    jr ROM_BETA         ;#3C6B  Finish, paging in DOS ROM.

;------------------------------------------------------------------------------
; Subroutine: INITVARS
; Address: #3CD6/15574
; Initialize DOS system variables.
; Called by: INITDOS.
;------------------------------------------------------------------------------
INITVARS                ;#3CD6
    ld a,0              ;       Reset A8-A15 address bus lines for IN.
    nop                 ;       Short pause of 8T.
    nop    
    in a,(247)          ;       Read port 247 of ZX Interface 1.
    cp 30               ;       Jump forward if it is not connected, skipping
    jr nz,INITVARS01    ;#3CE7  Interface 1 initialization.
    rst 8               ;       Otherwise, execute NEWVARS command to create
    defb #31            ;       extended Sinclair BASIC system variables.
    ld a,1              ;       Assign value 1 to the extended BASIC system
    ld (23791),a        ;       variable COPIES.

INITVARS01              ;#3CE7
    ld hl,CHANSCOPY-1   ;       Space of 112 bytes is created at 23734/#5CB5 by
    ld bc,112           ;       MAKE-ROOM subroutine (#1655/5717) of BASIC ROM
    call #1655          ;       (this ROM is enabled). Extended BASIC system 
                        ;       variables (if Interface 1 is present) and 
                        ;       channel information area are displaced.
    call ROMBETA_Q      ;#3CD8  Enable DOS ROM before crossing 15615/#3CFF
                        ;       boundary.
    ld hl,#FFFF         ;       Some variables will be initialized with #FFFF.
    ld (STEP_RATE),hl   ;       Flag #FF means stepping motor rate not yet 
    ld (STEP_RATE+2),hl ;       measured.
    ld (DSKTYPE),hl     ;       Flag #FF means none of 4 disks have their disk 
;##############################################################################
; End of addresses watched by Beta disk interface (15360-15615/#3C00-#3CFF).
;##############################################################################
    ld (DSKTYPE+2),hl   ;       type value initialized.
    xor a               ;       Some variables will be initialized with 0.
    ld (DEFLTDRV),a     ;       Default drive is "A".
    ld (IF1VAR),a       ;       Flag is 0, so IF1VSWP subroutine does nothing 
                        ;       when invoked for the first time.
    ld (D_ERRCOD),a     ;       No DOS error reported.
    ld (RM_FPC),a       ;       Don't delete floating point constant code.
    ld a,#FF            ;       Some variables will be initialized with #FF.
    ld (ERR_NR),a       ;       Value -1 corresponds to BASIC error 0.
    ld (PORT255),a      ;       Port 255 configuration set to: BASIC ROM 
                        ;       enabled, single density disk, side 0 of disk, 
                        ;       /HLT=1, /MASTER RESET=1 and drive D selected.
    ld (SV_DCFG),a      ;       Don't save disk configuration data (see 
                        ;       PRNCHR01).
    ld a,#D0            ;       Code for FDC 'FORCE INTERRUPT' command.
    out (31),a          ;       Send code to FDC command register.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: PRinT ENTER
; Address: #3D1F/15647
; Print 'Enter' character (#0D/13). Print cursor is moved to start of next 
;line.
; Called by: FILEENTRY01, DS_CAT.
;------------------------------------------------------------------------------
PRT_ENTER               ;#3D1F
    ld a,#0D            ;       Code of 'Enter' character.

;------------------------------------------------------------------------------
; Subroutine: PRINT CHAR 01
; Address: #3D21/15649
; Print character to the current stream. Disk configuration data stored into 
;printer buffer can be saved, depending on the SV_DCFG flag.
; Input:  A=character code;
;         (SV_DCFG)=0 (save config data in printer buffer).
; Note: BC, DE and HL register pairs are preserved.
; Called by: RST 16/RST #10/PRNCHR, PRT_ENTER.
;------------------------------------------------------------------------------
PRNCHR01                ;#3D21
    push hl             ;       Stack HL and BC.
    push bc    
    ld b,a              ;       Save code to print in B.
    ld a,(SV_DCFG)      ;       Fetch flag value and check if 0.
    or a    
    push af             ;       Stack Z flag.
    ld a,b              ;       Restore code to print.
    call z,SAVECFGS     ;#3918  Save disk configuration data in the printer
                        ;       buffer to a temporary place.
    call BAS_RST16      ;#3D37  Call BASIC RST 16 subroutine.
    pop af              ;       Unstack Z flag.
    call z,LOADCFGS     ;#392B  Recover disk configuration data.
    pop bc              ;       Unstack BC and HL.
    pop hl    
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: BASic RST 16
; Address: #3CD6/15671
; Call RST 16/RST #10 from BASIC ROM. Print character.
; Input:  A=character code.
; Called by: PRNCHR01.
;------------------------------------------------------------------------------
BAS_RST16               ;#3D37
    ld hl,16            ;       Address of BASIC routine.
    jp CALLBAS          ;#2E36  Call BASIC ROM routine.

;------------------------------------------------------------------------------
; Subroutine: RESTORE
; Address: #3D3D/15677
; Send 'RESTORE' command to FDC. It moves disk head to physical track 0.
; Called by: DS_FORMAT, RDWRSECT. 
;------------------------------------------------------------------------------
RESTORE                 ;#3D3D
    ld a,#0B            ;       Code of FDC 'RESTORE' command.

;------------------------------------------------------------------------------
; Subroutine: FDC CoMmanD
; Address: #3D3F/15679
; Send 1 byte command to FDC and wait until it finishes. Break key is monitored 
;and, if pressed, control is passed to BASIC monitor and 'L - BREAK into 
;program' error code is shown. 
; Input: A=FDC command code.
; Note: HL register pair is preserved.
; Called by: DSK_DETC, SCAN_SRATE, SEEK_A, TRACK_PA.
;------------------------------------------------------------------------------
FDC_CMD                 ;#3D3F
    out (31),a          ;       Send command to FDC command register.

FDC_CMD01               ;#3D41
    push hl             ;       Save HL value.
    ld hl,#1F54         ;       Call 'BREAK-KEY' subroutine of BASIC ROM; 
                        ;       return C flag=0 if BREAK was pressed.
    call CALLBAS        ;#2E36 
    ld hl,#1B7B         ;       Call REPORT-L OF BASIC ROM to print error 
    jp nc,CALLBAS       ;       message and current operation is stopped.
    pop hl              ;       Restore HL value.
    in a,(255)          ;       Read FDC INTRQ signal (port 255, bit 7). 0 
    and %10000000       ;       means command in progress, new attempt is made 
    jr z,FDC_CMD01      ;#3D41  until it is 1 (command terminated).
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: DiSK DETeCt
; Address: #3D56/15702
; Detect presence of disk into the drive and, if absent, raise error condition.
;'RESTORE' command is sent to drive and FDC will rotate the disk (besides, head 
;is moved towards track 0). During one disk revolution, INDEX signal pulses; 
;this subroutine probes INDEX and wait until it changes or, if maximum number 
;of retries are exceeded, raises 'no disk' error condition.
; Called by: SEL_DRIVE.
;------------------------------------------------------------------------------
DSK_DETC                ;#3D56
    ld a,#0B            ;       Sendo to FDC 'RESTORE' command to move disk 
    call FDC_CMD        ;#3D3F  head to track 0.
    ld de,0
    in a,(31)           ;       Read, for the first time, FDC status register 
    and %00000010       ;       and  mask out all bits but bit 1 (INDEX).
    ld b,a              ;       Store result in B register.

DSK_DETC01              ;#3D63
    in a,(31)           ;       Read status register again and mask out 
    and %00000010       ;       unneccessary bits.
    cp b                ;       If INDEX bit has changed, finish subroutine.
    ret nz    
    inc de              ;       Otherwise, increment counter and repeat unless
    ld a,e              ;       number of retries was over.
    or d
    jr nz,DSK_DETC01    ;#3D63 
    jp ER_NODISK        ;#3E82  Jump to raise 'no disk' error condition.

;------------------------------------------------------------------------------
; Subroutine: SELect DRIVE
; Address: #3D71/15729
; Select current drive unit. Detect stepping motor rate and number of tracks of 
;the drive, if this was not done yet. SEL_DRIVE01 entry point also changes the 
;current drive.
; Output: (STEP_RATE+drive)=drive rate;
;         (DSKTYPE+drive)=drive type (#00=40 tracks/#80=80 tracks).
; Called by: DOSMAIN, DS_DRV, COPYALL, DS_COPY, GET_DRV, STREAMDRV. 
;------------------------------------------------------------------------------
SEL_DRIVE               ;#3D71
    ld a,(DEFLTDRV)    ;       Fetch current drive number (0-3).
;------------------------------------------------------------------------------
; SEL_DRIVE01 (#3D74/15732)
; Entry point used to change current drive.
; Input:  A=drive number (0-3).
; Output: (CURRDRIVE)=current drive number (0-3).
;------------------------------------------------------------------------------
SEL_DRIVE01             ;#3D74
    ld (CURRDRIVE),a    ;       Store current drive number into variable.
    ld hl,PORT255       ;       Variable with last byte sent to port 255.
    ld c,a              ;       C=drive number
    ld a,%00111100      ;       Raise bits 2-5 (/MASTER RESET, /HLT, SIDE 
    or c                ;       SELECT) and send drive to select to port 255.
    out (255),a
    ld (hl),a           ;       Update PORT255 DOS system variable.
    call FT_STEPRT      ;#3DB1  Get stepping motor rate of current drive.
    and %10000000       ;       Jump forward if #FF flag (bit 7 high) is not 
    jr z,SEL_DRIVE03    ;#3DA3  found, i.e., rate already has been measured.
    call DSK_DETC       ;#3D56  Check presence of disk in the drive.
    call SCAN_SRATE     ;#3DBF  Measure rate of stepping motor.
    call FT_DSKTYPE     ;#3DBA  Fetch data of current disk type.
    cp #FF              ;       Jump forward if its type had been already 
    jr nz,SEL_DRIVE03   ;#3DA3  detected, i.e., it is not #FF.
    push hl             ;       Save pointer.
    call SCAN_NTRK      ;#3077  Measure number of tracks of disk.
    pop hl              ;       Restore pointer.
    cp 80
    ld a,#00            ;       A=#00 if number of tracks is 40.
    jr nz,SEL_DRIVE02   ;#3DA2 
    ld a,#80            ;       A=#80 if number of tracks is 80.

SEL_DRIVE02             ;#3DA2
    ld (hl),a           ;       Save disk type in the system variable.

SEL_DRIVE03             ;#3DA3
    call CURRTRACK      ;#2EE3  Update FDC track register.
                        ;       Wait for 0.15 s before returning.

;------------------------------------------------------------------------------
; Subroutine: DELAY
; Address: #3DA6/15782
; Delay of 524546T, approximately 0.15 s.
; Called by: SCAN_NTRK, WAITINTRQ, TRACK_PA.
;------------------------------------------------------------------------------
DELAY                   ;#3DA6
    ld a,128            ;       Repeat 128 times.                       [7T]
;------------------------------------------------------------------------------
; Subroutine: DELAY01
; Address: #3DA8/15784
; Delay routine which time is calculated as (4098A-5)T, where T is inverse of
;Z80 CṔU clock frequency. If A=0, must be replaced with 256 in the equation.
; Input:  A=number of cycles.
; Output: A=C=0
; Called by: FLIPHLT, DELAY, LONGDELAY.
; Note: the number of T periods spent by each assembly instruction is written 
;enclosed by brackets
;------------------------------------------------------------------------------
DELAY01                 ;#3DA8
    ld c,255            ;       Repeat 255 times.                       [7T]
DELAY02                 ;#3DAA
    dec c               ;       Execute inner loop until C is           [4T]  
    jr nz,DELAY02       ;#3DAA  decremented to 0.                   [7T/12T]
    dec a               ;       Execute outer loop until C is           [4T]
    jr nz,DELAY01       ;#3DA8  decremented to 0.                   [7T/12T]
    ret                 ;       End of subroutine.                     [10T]

;------------------------------------------------------------------------------
; Subroutine: FeTch STEPping motor RaTe 
; Address: #3D1B/15793
; Fetch stepping motor rate of current drive.
; Output: A=stepping rate value (%00-%11);
;         HL=address of current drive element of STEP_RATE array.
; Called by: SCAN_NTRK, SEL_DRIVE, SCAN_SRATE, TRACK_LA, RDWRSECT. 
;------------------------------------------------------------------------------
FT_STEPRT               ;#3DB1
    ld de,STEP_RATE     ;       DE points to stepping rate of drive 0.

;------------------------------------------------------------------------------
; This part is common for FT_SETPRT and FT_DSKTYPE.
;------------------------------------------------------------------------------
FETCHVAR                ;#3DB4
    ld hl,(CURRDRIVE)   ;       Fetch current drive number (0-3) and add to 
    add hl,de           ;       address of system variable. HL points to 
                        ;       current drive data. The next byte of CURRDRIVE 
                        ;       must be 0 (see ZEROVAR).
    ld a,(hl)           ;       Fetch data.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: FeTch DiSK TYPE
; Address: #3DBA/15802
; Fetch drive type (see 'DSKTYPE' DOS system variable) of current drive.
; Output: A=disk type;
;         HL=address of current drive element of DSKTYPE array.
; Called by: ID_TYPE, WRSECTORS, DS_FORMAT, DS_40, DS_80, DS_GOTO, SEL_DRIVE, 
;TRACK_LA. 
;------------------------------------------------------------------------------
FT_DSKTYPE              ;#3DBA
    ld de,DSKTYPE       ;       DE points to disk type of drive 0.
    jr FETCHVAR         ;#3DB4  Jump backward and fetch variable data.

;------------------------------------------------------------------------------
; Subroutine: SCAN Stepping motor RATE
; Address: #3DBF/15807
; Rate of the disk head stepping motor is measured for the best performance.
;Rate can have one of the following values: %11 (30 ms); %10 (20 ms); %01 (12
;ms); %00 (6 ms). STEP_RATE is an array of 4 elements that stores rates of all
;drives.
; Input:  HL=address of STEP_RATE element of the drive to be measured.
; Output: (STEP_RATE+drive)=drive rate.
; Called by: SEL_DRIVE.
;------------------------------------------------------------------------------
SCAN_SRATE              ;#3DBF
    call FT_STEPRT      ;#3DB1  HL=address of STEP_RATE of the current drive.
    ld b,%00001000      ;       Initial rate is %00 (bit 3=1 to set head load).
    ld c,4              ;       There are 4 possible rate values to try.

SCAN_SRATE01            ;#3DC6
    ld (hl),b           ;       Store rate into STEP_RATE of current drive.
    ld a,#0B            ;       Send 'RESTORE' command to move head to track 0. 
    call FDC_CMD        ;#3D3F  Rate is %11 (slowest and safest value).
    ld a,32             ;       Track 32.
    ld b,#0B            ;       Send 'SEEK' command to move head to track 32. 
    call SEEK_A         ;#3DED  Rate is %11 (slowest and safest value).
    ld b,(hl)           ;       Fetch rate to be tried.
    ld a,1              ;       Send 'SEEK' command to move head to track 1. 
    call SEEK_A         ;#3DED  
    in a,(31)           ;       Read FDC status register and mask out all bits 
    and %00000100       ;       except bit 2 (TRACK00). This bit is 1 if head
                        ;       is on track 0 of disk.
    jr nz,SCAN_SRATE02  ;#3DE8  Jump backward to retry if head was on track 0
                        ;       (it was expected to find head on track 1).
    xor a               ;       Send 'SEEK' command to move head to track 0.
    call SEEK_A         ;#3DED
    in a,(31)           ;       Read FDC status register and mask out all bits 
    and %00000100       ;       except bit 2 (TRACK00).
    ret nz              ;       Exit if head was on track 0 as expected.

SCAN_SRATE02            ;#3DE8
    inc b               ;       Increment rate.
    dec c               ;       Decrement counter and finish if it is 0 and
    ret z               ;       hence rate is %11.
    jr SCAN_SRATE01     ;#3DC6  Otherwise, retry with another rate.

;-----------------------------------------------------------------------------
; Subroutine: SEEK A
; Address: #3DED/15853
; Send 'SEEK' command to FDC. Disk head will be moved towards the track with
;physical number that is equal to the value in A. The 1-byte command code is:
;bits 4-7=%0001 (seek command), bit 3=1 (set head load flag), bit 2=0 (do not 
;verify track number), bits 0-1=stepping motor rate.
; Input: A=physical track number;
;        B=stepping motor rate.
; Called by: SCAN_NTRK, FMTDISK, SCAN_SRATE, READTRACK.
;-----------------------------------------------------------------------------
SEEK_A                  ;#3DED
    out (127),a         ;       Send A to FDC data register.
    ld a,b              ;       FDC 'SEEK' command code is made with stepping 
    or %00011000        ;       motor rate given by B.
    jp FDC_CMD          ;#3D3F  Send command to FDC.

;-----------------------------------------------------------------------------
; Subroutine: TRACK Physical A
; Address: #3DF5/15861
; Move disk head to physical track number in A. After SEEK command completed by 
;FDC, the subroutine wait for 0,147 s if head was not on the track, but if 
;head was already on it, finishes immediately.
; Input: A=physical track ID;
;        B=stepping motor rate.
; Called by: TRACK_LA.
;-----------------------------------------------------------------------------
TRACK_PA                ;#3DF5
    out (127),a         ;       Send track number to FDC data register.
    push bc             ;       Stack stepping rate value.
    ld b,a              ;       Store rate into B register.
    in a,(63)           ;       Read FDC track register.
    cp b                ;       Compare with desired track number.
    pop bc              ;       Unstack stepping rate value.
    push af             ;       Stack Z flag.
    ld a,b              ;       Take rate value and raise bits 3 and 4 to make 
    or %00011000        ;       FDC 'SEEK' command. This command moves head to 
                        ;       track number in the track register.
    call FDC_CMD        ;#3D3F 
    pop af              ;       Unstack Z flag.
    ret z               ;       Finish if head was already positioned.
    push bc             ;       Save rate.
    call DELAY          ;#3DA6  Wait 0.15 s.
    pop bc              ;       Recover rate.
    ret                 ;       End of subroutine.

;-----------------------------------------------------------------------------
; Subroutine: TRACK Logical A
; Address: #3E0C/15884
; Move disk head to logical track number in A.
; Input:  A=logical track ID.
; Called by: RW_SECTORS, LDSVBUFF02, RDWRSECT.
;-----------------------------------------------------------------------------
TRACK_LA                ;#3E0C
    ld c,a              ;       C=logical track number.
    call SELSIDE0       ;#3089  Select side 0 of disk.
    call FT_DSKTYPE     ;#3DBA  Fetch data of current disk type.
    and %00000010       ;       Calculate physical track number and select side 
    call nz,PHYSTRACK   ;#3E47  of disk if it is double side type.
    push bc             ;       Stack track number.
    bit 7,(hl)          ;       Jump forward if disk has 40 tracks.
    jr z,TRACK_LA02     ;#3E2C 
    bit 0,(hl)          ;       Jump forward if disk has 80 tracks.
    jr nz,TRACK_LA02    ;#3E2C 
    in a,(63)           ;       Read FDC track register.
    cp c    
    jr z,TRACK_LA01     ;#3E2B 
    rlca    
    out (63),a
    ld a,c    
    rlca    

TRACK_LA01              ;#3E2B
    ld c,a    

TRACK_LA02              ;#3E2C
    call FT_STEPRT      ;#3DB1  B is stepping motor rate. This value is used by
    ld b,a              ;       TRACK_PA to make code of 'SEEK' FDC command.
    ld a,c
    call TRACK_PA       ;#3DF5  Move head to physical track in A.
    pop bc              ;       Unstack track number.
    ld a,c              ;       Send this value to FDC track register.
    out (63),a
    ld a,(NOTREADY)     ;       Return immediately if flag is 0, otherwise
    or a                ;       make a delay (drive is not ready).
    ret z

;------------------------------------------------------------------------------
; Subroutine: LONG DELAY
; Address: #3E3D/15993
; Delay of 3135225T, approximately 0.9 s.
; Called by: DS_FORMAT, NMI01, TRACK_LA, RDWRSECT.
;------------------------------------------------------------------------------
LONGDELAY               ;#3E3D
    ld b,3              ;       Repeat next loop 3 times.               [7T]

LONGDELAY01             ;#3E3F
    ld a,255            ;       Initialize time parameter.              [7T]
    call DELAY01        ;#3DA8  Delay of 1045002T period.              [17T]
    djnz LONGDELAY01    ;#3E3F  Repeat 3 times.                     [13T/8T]
    ret                 ;       End of subroutine.                     [10T]
   
;------------------------------------------------------------------------------
; Subroutine: PHYSical TRACK
; Address: #3E47/15943
; Disk is organized in logical tracks numbered sequentially starting from track 
;0. In the single sided disk, both logical and physical track numbers have same
;values. In double sided disk, physical track number is same for both sides of
;disk, but logical track number take also in account the side. This is done to 
;minimize head movement during sequential reading of data across tracks. The 
;algorithm that converts logical track to physical track number is:
; -rotate bits of logical track number to right (division by 2);
; -check bit 0 that has been moved to C flag (remainder of division), then
;  0=side 0 or 1=side 1.
; Input:  C=logical track number.
; Output: C=physical track number;
;         A=physical track number;
;         C flag=1 for side 1.
; Called by: TRACK_LA.
;------------------------------------------------------------------------------
PHYSTRACK               ;#3E47
    ld a,c              ;       A=logical track number.
    or a                ;       C flag=0.
    rra                 ;       A=A/2 (remainder is in C flag).
    ld c,a              ;       C=physical track number.
    ret nc              ;       Finish if logical track number was even but
    jp SELSIDE1         ;#30A3  select disk side 1 if odd.

;------------------------------------------------------------------------------
; Subroutine: READ TRACK
; Address: #3E4F/15951
; Return FDC track register value.
; Output: H=track number.
; Called by: CURRTRACK, DS_FORMAT. 
;------------------------------------------------------------------------------
READTRACK               ;#3E4F
    call SELSIDE0       ;#3089  Select side 0 of disk.

;------------------------------------------------------------------------------
; READTRACK01 (#3E52/15954)
; Entry point used by DS_FORMAT, omit side 0 selection.
;------------------------------------------------------------------------------
READTRACK01             ;#3E52
    in a,(31)           ;       Read FDC status register.
    and %10000000       ;       Mask out undesired bits, leave only NOT_READY 
    ld (NOTREADY),a     ;       bit and store in the system variable.
    in a,(63)           ;       Read FDC track register.
    ld h,a              ;       H=track number.
    call SEEK_A         ;#3DED  Move head to track read from register.
    ld c,127            ;       C=FDC data register port address.
    ld d,1              ;       Second byte of number of attempts.
    ld a,#C0            ;       Send 'READ ADDRESS' command to FDC command 
    out (31),a          ;       register.
    push bc             ;       Stack port address.
    ld b,3              ;       MSB of number of attempts.

READTRACK02             ;#3E6A
; This loop does repeating reads from port 255 and awaits for DRQ=1 (FDC has
;data to be read) or INTRQ=1 (FDC command finished).
    in a,(255)          ;       Read port 255 and mask out unnecessary bits.
    and %11000000
    jr nz,READTRACK03   ;#3E8D  Jump out of the loop if bit 6 or 7 are 1.
    inc de              ;       B, D and E form a 3-byte counter for number of 
    ld a,e              ;       attempts to read port 255.　Each failed attempt 
    or d                ;       changes value of  counter and, if it reaches 0, 
    jr nz,READTRACK02   ;#3E6A  exit loop. This counter is rather odd: B is
    djnz READTRACK02    ;#3E6A  decremented but DE is incremented.
    pop bc              ;       Unstack port address.
    ld a,#D0            ;       Send 'FORCE INTERRUPT' to FDC command register
    out (31),a          ;       to stop command in progress.
    ld a,(NODISK)       ;       Check (NODISK) flag. Return silently if flag is 
    cp #FF              ;       #FF; otherwise, 'no disk' error is raised.
    ret z    

;------------------------------------------------------------------------------
; Error routine: NO DISK
; Address: #3E82/16002
; Disk was not detected in the drive.
; Called by: READTRACK, DSK_DETC, READSECTOR.
;------------------------------------------------------------------------------
ER_NODISK               ;#3E82
    call ERROR_R        ;#379F  Set BASIC error code "R".
    ld a,#FF            ;       Flag: printer buffer will be saved.
    ld (FLAGBUFF),a
    jp ER_NODISK01      ;#378F  Jump backward to error routine.

;------------------------------------------------------------------------------
; Part of READTRACK subroutine.
; READTRACK03 (#3E8D/15954): read track ID from disk.
; READTRACK04 (#3E90/15978): read all remaining data and discard them.
;------------------------------------------------------------------------------
READTRACK03             ;#3E8D
    pop bc              ;       Unstack port address.
    in h,(c)            ;       Read track ID.

READTRACK04             ;#3E90
    in a,(255)          ;       Read port 255 and mask out all bits except DRQ 
    and %11000000       ;       and INTRQ signals.
    jr z,READTRACK04    ;#3E90  Wait until either signal is 1.
    ret m               ;       Return if INTRQ=1 (command finished).
    in a,(127)          ;       Read data from FDC data register.
    jr READTRACK04      ;#3E90  Jump to read next byte.

;------------------------------------------------------------------------------
; Subroutine: SAVe START Sector
; Address: #3E9B/16027
; Save start sector ID for reading/writing operation.
; Input:  A=logical sector ID (0-15).
; Called by: RW_SECTORS.
;------------------------------------------------------------------------------
SAV_STARTS              ;#3E9B
    ld (STARTSECT),a    ;       Store sector ID into DOS system variable.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: SAVe Read/Write ADDress
; Address: #3E9F/15943
; Save address of RAM pointed by HL for reading/writing operation.
; Called by: RW_SECTORS.
;------------------------------------------------------------------------------
SAV_RWADD               ;#3E9F
    ld (RWADDRESS),hl   ;       Put HL into this system variable.
    ret                 ;       End of subroutine.

;------------------------------------------------------------------------------
; Subroutine: WRITE SECTOR 
; Address: #3EA3/16035
; Write one sector to disk.
; Input: (STARTSECT)=start sector;
; Called by: RW_SECTORS.
;------------------------------------------------------------------------------
WRITESECTOR             ;#3EA3
    ld a,#A0            ;       Code of 'WRITER SECTOR' FDC command.
    jr RDWRSECT         ;#3EA9  Jump to RWSECTOR subroutine.

;------------------------------------------------------------------------------
; Subroutine: READ SECTOR 
; Address: #3EA7/16039
;
; Called by: RW_SECTORS.
;------------------------------------------------------------------------------
READSECTOR              ;#3EA7
    ld a,#80            ;       Code of 'READ SECTOR' FDC command.

;------------------------------------------------------------------------------
; RDWRSECT (#3EA9/16041)
; This part is common for WRITE SECTOR and READ SECTOR subroutines.
; 
;------------------------------------------------------------------------------
RDWRSECT                ;#3EA9
    ld (RW_CMD),a       ;       Store FDC command into system variable.

RDWRSECT01              ;#3EAC
    ld d,10             ;       Max number of attempts after an error.

RDWRSECT02              ;#3EAE
    push de             ;       Stack attempts count.
    ld a,(STARTSECT)    ;       Fetch logical sector number (0-15), convert to
    inc a               ;       physical sector number (1-16) and send to FDC
    out (95),a          ;       sector register.
    ld hl,(RWADDRESS)   ;       HL=start address of RAM to perform read/write.
    ld c,127            ;       C=FDC data register port address.
    ld a,(RW_CMD)       ;       Fetch READ/WRITE SECTOR command and send to 
    out (31),a          ;       FDC.
    cp #A0              ;       Z flag is 1 for WRITE SECTOR command or is 
    push af             ;       0 for READ sector. Flag is saved onto stack.
    call z,FDC_WDATA    ;#3F50  Send 256 bytes of data to FDC.
    pop af              ;       Recover flag from stack.
    call nz,FDC_RDATA   ;#3F6B  Read 256 bytes from FDC.
    pop de              ;       Unstack attempts count.
    in a,(31)           ;       Read FDC status register and save into B 
    ld b,a              ;       register.
    and %01111111       ;       Mask out bit 7. Finish subroutine if no error 
    ret z               ;       was detected (i.e. bits 0-6 are all 0).

RDWRSECT03              ;#3ED0
; An error occurred and will be handled. 
    ld hl,M_RDONLY      ;#397D  "Read only" error message.
    and %01000000       ;       Test bit 6 of status register (PROTECT) and 
    jr nz,RDWRSECT05    ;#3EE2  jump forward if nonzero (write protect error).
    ld a,b              ;       Test bit 2 of status register (LOST DATA) 
    and %00000100       ;       and jump forward if 0.
    jr z,RDWRSECT09     ;#3F36 
    dec d               ;       Decrement counter and retry operation unless 
    jr nz,RDWRSECT02    ;#3EAE  count is zero.

RDWRSECT04              ;#3EDF
; This is a generic disk error handler.
    ld hl,M_DSKERR      ;#3987  Disk error message address.

RDWRSECT05              ;#3EE2
    ld a,#D0            ;       Send 'FORCE INTERRUPT' command to FDC. Stop any
    out (31),a          ;       operation in progress.
    ld a,b              ;       Fetch value read from FDC status register.
    and %00000001       ;       Test bit 0 of status register (BUSY). If it is 
    jp nz,ER_NODISK     ;#3E82  1, jump to 'no disk' error routine.
    in a,(63)           ;       Read FDC track register.
    or a                ;       Jump forward if track ID is not 0; otherwise,
    jr nz,RDWRSECT06    ;#3EF6  read FDC sector register. Return silently if it 
    in a,(95)           ;       is sector 9 (physical sector 10) and track 0. 
    cp 10               ;       This sector is used to save printer buffer when 
    ret z               ;       disk is not protected.

RDWRSECT06              ;#3EF6
; Print error message, track and sector ID and ask if user wanto to retry, 
;abort or ignore.
    push hl             ;       Stack error message string address.
    call BAS_CLS        ;#2E33  Clear screen.
    pop hl              ;       Unstack error message string address.
    rst 24              ;       Print error message.
    ld hl,M_TRK         ;#39B8  Print 'Enter' and "Trk ".
    rst 24
    in a,(63)           ;       Read FDC track register.
    call PRINTN_A       ;#390C  Print numeric value of A.
    ld hl,M_SEC         ;#39BD  Print ' sec'.
    rst 24
    in a,(95)           ;       Read FDC sector register.
    call PRINTN_A       ;#390C  Print numeric value of A.
    ld hl,M_RETRY       ;#39A3  Print "Retry,Abort,Ignore? (Y/N)"
    rst 24

RDWRSECT07              ;#3F12
; This loop awaits for user key press.
    call READKEY        ;#2515  Read keys.
    cp 73               ;       Finish subroutine if "I" (Ignore) was pressed.
    ret z    
    cp 82               ;       Jump forward to retry if "R" was pressed.
    jr z,RDWRSECT08     ;#3F2B 
    cp 65               ;       Jump backward to repeat key reading if "A" was 
    jr nz,RDWRSECT07    ;#3F12  not pressed.
    call ERROR_R        ;#379F  Otherwise, set BASIC error "R" and set DOS 
    ld a,7              ;       error code 7 (disk error).
    ld (D_ERRCOD),a
    jp DSTM_RET         ;#2170  Return to DOS interpreter.

RDWRSECT08              ;#3F2B
; Retry operation after 'R' key press.
    in a,(63)           ;       Read FDC track register.
    call TRACK_LA       ;#3E0C  Move head onto this track number.
    call LONGDELAY      ;#3E3D  Wait for 0.9 s.
    jp RDWRSECT01       ;#3EAC  Jump backward to retry operation.

RDWRSECT09              ;#3F36
; Retry operation after incrementing stepping motor rate.
    dec d               ;       Decrement number of attempt count and 
    jp z,RDWRSECT04     ;#3EDF  jump to error handler if result is 0.
    push de             ;       Stack attempt count.
    call FT_STEPRT      ;#3DB1  Fetch stepping motor rate.
    and %00000010       ;       Increment rate if it is less than %10 (max
    jr nz,RDWRSECT10    ;#3F43  rate is %11).
    inc (hl)    

RDWRSECT10              ;#3F43
    call RESTORE        ;#3D3D  Move head to track 0.
    ld a,(RWTRKID)      ;       Then move head to track where read/write
    call TRACK_LA       ;#3E0C  operation is being carried out.
    pop de              ;       Unstack attempt count.
    jp RDWRSECT02       ;#3EAE  Repeat operation.

;------------------------------------------------------------------------------
; Subroutine: FDC WRITE DATA
; Address: #3F50/16208
; Send data requested by FDC during command operation. Used to write one sector
;to disk.
; Input: HL=address of data to write to FDC;
;        C=FDC data register port address (#7F/127).
; Called by: READSECTOR.
;------------------------------------------------------------------------------
FDC_WDATA               ;#3F50
    ld b,4              ;       Counter for number of attempts.

FDC_WDATA01             ;#3F52
; Read port 255 until DRQ=1 (FDC is requesting data) or INTRQ=1 (command 
;terminated) is issued by FDC. This loop is controlled by 3-bytes counter with
;registers B, D and E. Whereas DE is increased, B is decreased.
    in a,(255)          ;       Read FDC DRQ (bit 6) and INTRQ (bit 7) signals.
    and %11000000       ;       Ignore bits 0-5 and test 6 and 7. Jump forward 
    jr nz,FDC_WDATA03   ;#3F67  if FDC are requesting data (DRQ=1) or command 
                        ;       is finished (INTRQ=1).
    inc de              ;       Increment attempts count.
    ld a,e    
    or d
    jr nz,FDC_WDATA01   ;#3F52  Retry reading port 255 if DE is not 0.
    djnz FDC_WDATA01    ;#3F52  Decrement B counter and repeat if not 0.
    ret                 ;       End of sub-routine.
;------------------------------------------------------------------------------
; FDC_WDATA02 (#3F60/16224)
; This entry point is used by NMI_WRSEC. It omits initial DRQ/INTRQ read loop 
;that waits for FDC data requisition or finished command signal. 
;------------------------------------------------------------------------------
FDC_WDATA02             ;#3F60
    in a,(255)          ;       Read FDC DRQ (bit 6) and INTRQ (bit 7) signals.
    and %11000000       ;       Ignore bits 0-5 and test 6-7.
    jr z,FDC_WDATA02    ;#3F60  Repeat until one of the bits is raised.
    ret m               ;       Finish if bit 7 (INTRQ) is 1 (operation 
                        ;       completed).
FDC_WDATA03             ;#3F67
    outi                ;       Send data read from (HL) to data register.
    jr FDC_WDATA02      ;#3F60  Repeat for next byte or end of FDC operation.

;------------------------------------------------------------------------------
; Subroutine: FDC READ DATA
; Address: #3F6B/16235
; Read data sent by FDC during command operation. Used to read data of one disk
;sector.
; Input: HL=memory address where data read from FDC will be written to;
;        C=FDC data register port address (#7F/127).
; Called by: READSECTOR.
;------------------------------------------------------------------------------
FDC_RDATA               ;#3F6B
    ld b,4              ;       Counter for number of attempts.

FDC_RDATA01             ;#3F6D
; Read port 255 until DRQ=1 (FDC is requesting data) or INTRQ=1 (command 
;terminated) is issued by FDC. This loop is controlled by 3-bytes counter with
;registers B, D and E. Whereas DE is increased, B is decreased.
    in a,(255)          ;       Read FDC DRQ (bit 6) and INTRQ (bit 7) signals.
    and %11000000       ;       Mask out unnecessary bits.
    jr nz,FDC_RDATA03   ;#3F82  Jump forward if FDC are requesting data (DRQ=1) 
                        ;       or command was finished (INTRQ=1).
    inc de              ;       Increment counter of number of attempts.
    ld a,e
    or d                ;       Jump backward and do new reading of port 255
    jr nz,FDC_RDATA01   ;#3F6D  if counter is not 0.
    djnz FDC_RDATA01    ;#3F6D  Decrement B counter and repeat if not 0.
    ret                 ;       End of sub-routine.

;------------------------------------------------------------------------------
; FDC_RDATA02 (#3F7B/16251)
; This entry point is used by NMI_RDSEC01 and FMT_TRK. It omits initial 
;DRQ/INTRQ read loop that waits for FDC data requisition or finished command 
;signal. 
;------------------------------------------------------------------------------
FDC_RDATA02             ;#3F7B
    in a,(255)          ;       Read FDC DRQ (bit 6) and INTRQ (bit 7) signals.
    and %11000000       ;       Mask out unnecessary bits.
    jr z,FDC_RDATA02    ;#3F7B  Jump backward and make new attempt if bits 6-7 
                        ;       are 0.
    ret m               ;       Finish if bit 7 (INTRQ) is 1 (operation 
                        ;       terminated).
FDC_RDATA03             ;#3F82
    ini                 ;       Read data register and write byte to (HL).
    jr FDC_RDATA02      ;#3F7B  Jump backward to read next byte or to finish
                        ;       operation.
;------------------------------------------------------------------------------
; Subroutine: FILE ENTRY
; Address: #3F86/16262
; Seek for directory entry in the printer buffer, skipping deleted files. When
;end of directory marker is found, print number of free sectors and return to
;DOS interpreter (thus, exiting from DS_CAT statement routine).
; Input HL=pointer for directory entry in printer buffer.
; Called by: DS_CAT.
;------------------------------------------------------------------------------
FILEENTRY               ;#3F86
    call NXTDIRSEC      ;#2473  Check pointer position and read next sector if
                        ;       printer buffer limit was exceeded.
    ld a,(hl)           ;       Fetch first byte of entry.
    or a                ;       Exit loop if end of directory was detected 
    jp z,FILEENTRY01    ;#232B  (i.e., first byte of entry is 0).
    cp 1                ;       When erased file entry was found (i.e., first 
    call z,ADDHL16      ;#246E  byte of entry is 1) advance pointer to next 
    ret nz              ;       entry and repeat checking; otherwise, return if 
    jr FILEENTRY        ;#3F86  real file was found.

;------------------------------------------------------------------------------
; Subroutine: LOAD BUFFer
; Address: #3F96/16278
; Restore printer buffer (23296-23551/#5B00-5BFF) from disk track 0, sector 9.
;Value #AA is assigned to FLAGBUFF to prevent further attempt to load buffer.
; Called by: DSTM_RET, LOADARG, CH_OUT02, NEWSEGMT, RD_STMFENT, LASTSECTOR.
;------------------------------------------------------------------------------
LOADBUFF                ;#3F96
    ld a,#AA            ;       Assign flag #AA to FLAGBUFF.
    ld (FLAGBUFF),a
;------------------------------------------------------------------------------
; LOADBUFF01 (#3F9B/16283)
; Entry point called by SAVEFILE.
;------------------------------------------------------------------------------
LOADBUFF01              ;#3F9B
    xor a               ;       A=#00, 'read from sector' flag.
    jr LDSV_BUFF        ;#3FA0  Jump to the routine that loads/saves buffer.

;------------------------------------------------------------------------------
; Subroutine: SAVE BUFFer
; Address: #3F9E/16286
; Save printer buffer (23296-23551/#5B00-5BFF) into disk track 0, sector 9.
; Called by: READT0SX.
;------------------------------------------------------------------------------
SAVEBUFF                ;#3F9E
    ld a,#ff            ;       A=#FF, 'write to sector' flag.

;------------------------------------------------------------------------------
; LDSV_BUFF (#3FA0/16288)
; Common part for LOADBUFF and SAVEBUFF.
;------------------------------------------------------------------------------
LDSV_BUFF               ;#3FA0
    ld (FLAGRW),a       ;       Store Read/Write flag.
    ld de,#0009         ;       D=track 0, E=sector 9.

;------------------------------------------------------------------------------
; Subroutine: LoaD/SaVe BUFFer 01
; Address: #3FA6/16294
; Save/read printer buffer area to/from disk.
; Input: (FLAGRW)=#FF (write sector)/ #00 (read sector).
; Called by: LOADBUFF, SAVEBUFF, LASTSECTOR.
;------------------------------------------------------------------------------
LDSVBUFF01              ;#3FA6
    ld b,1              ;       Read/save 1 sector.
    ld hl,BUFFER        ;       Start address is 23296/#5B00.
    jp LDSVBUFF02       ;#2F14  Jump backward to continue subroutine.

;-----------------------------------------------------------------------------
; Subroutine: LAST SECTOR
; Address: #3FAE/16302
; When reading data from disk, there is no way to get less than 256 bytes (1
;sector). To avoid unused part of the last sector overwriting RAM data, this
;sector is written into printer buffer. Then, only the neccessary data of the 
;sector is copied to RAM.
; Input: HL=address to write data;
;        (VAR_C)=length of data;
;        B=0;
;        (FLAGRW)=#00.
; Called by: FILELOAD01.
;-----------------------------------------------------------------------------
LASTSECTOR              ;#3FAE
    push hl             ;       Stack address.
    ld de,(RWSECID)     ;       Fetch start track and sector ID numbers.
    call LDSVBUFF01     ;#3FA6  Read sector into printer buffer.
    ld a,(VAR_C_L)      ;       Fetch size of data in the last sector.
    pop de              ;       DE=address where last sector will be written.
    or a                ;       Jump to restore printer buffer if there is no 
    jr z,LOADBUFF       ;#3F96  byte to save in the last sector.
    ld c,a              ;       BC=length of block to copy.
    ld hl,BUFFER        ;       HL=address of printer buffer.
    ldir                ;       Copy block.
    jr LOADBUFF         ;#3F96  Jump to restore printer buffer.

;==============================================================================
; DOS Statement tables
; --------------------
; DOS interpreter operation is commanded by statements. In the same way of
;Sinclair BASIC, each statement is defined by 1-byte code and is printed in the
;screen as reserved words (tokens). A DOS command line/program line begins with
;a statement that can be followed by numeric or string arguments and ends with
;a end of line marker ('enter', #0D or 13).
;==============================================================================

;-----------------------------------------------------------------------------
; Table of DOS statement codes (#3FC5/16325)
; There are 19 different statements codes in this version of BASIC.
;-----------------------------------------------------------------------------
T_DSTMCOD
    defb #CF            ;       CAT
    defb #2A            ;       *
    defb #D0            ;       FORMAT
    defb #D1            ;       MOVE
    defb #E6            ;       NEW
    defb #D2            ;       ERASE
    defb #EF            ;       LOAD
    defb #F8            ;       SAVE
    defb #FE            ;       RETURN
    defb #BE            ;       PEEK
    defb #F4            ;       POKE
    defb #D5            ;       MERGE
    defb #F7            ;       RUN
    defb #D3            ;       OPEN #
    defb #D4            ;       CLOSE #
    defb #FF            ;       COPY
    defb #34            ;       4
    defb #EC            ;       GO TO
    defb #38            ;       8

;-----------------------------------------------------------------------------
; Table of DOS statement routine addresses (#3FD8/16344)
; This table lists start address of each statement routines available in DOS.
;-----------------------------------------------------------------------------
T_DSTMADD
    defw DS_CAT         ;#23B2 
    defw DS_DRV         ;#24A1 
    defw DS_FORMAT      ;#2F6F 
    defw DS_MOVE        ;#27FF 
    defw DS_NEW         ;#24B7 
    defw DS_ERASE       ;#272B 
    defw DS_LOAD        ;#294C 
    defw DS_SAVE        ;#2B7A 
    defw DS_RETURN      ;#2D94 
    defw DS_PEEK        ;#2A73 
    defw DS_POKE        ;#2A77 
    defw DS_MERGE       ;#2A7F 
    defw DS_RUN         ;#2DDF 
    defw DS_OPEN        ;#3213 
    defw DS_CLOSE       ;#36C7 
    defw DS_COPY        ;#2645 
    defw DS_40          ;#393C 
    defw DS_GOTO        ;#3AD0 
    defw DS_80          ;#3953 

;-----------------------------------------------------------------------------
; Unused bytes (#3FFE/16382)
;-----------------------------------------------------------------------------
    defb #FF,#FF

;    end

;##############################################################################
; Labels
; Some addresses and constants are replaced by labels to improve readability.
;Routines, subroutines and tables have their labels defined in the disassembly
;listing body. Labels defined by 'equ' pseudo-instructions are in this section.
;##############################################################################

;==============================================================================
; Offset from start of configuration sector (see 'Format of Beta diskette')
;==============================================================================
CS_DEND     equ 0       ; End of directory marker (0).
CS_FREES    equ 225     ; First free logical sector (0-15).
CS_FREET    equ 226     ; First free logical track.
CS_DTYPE    equ 227     ; Disk type: 22/#16/%00010110=double side/80 tracks; 
                        ;            23/#17/%00010111=double side/40 tracks; 
                        ;            24/#18/%00011000=single side/80 tracks; 
                        ;            25/#19/%00011001=single side/40 tracks.
CS_NFILE    equ 228     ; Count of files in the disk, including erased ones.
CS_NFREE    equ 229     ; Number of free sectors.
CS_IDENT    equ 231     ; ID of BETA disk (#10 or 16).
CS_ERASF    equ 244     ; Number of erased files.
CS_LABEL    equ 245     ; Disk label (8 characters).

;==============================================================================
; VIDEO RAM
; Start of the RAM. Used as temporary workspace by NMI and DS_GOTO routines.
;==============================================================================
VID_RAM     equ 16384   ;#4000

;==============================================================================
; Printer buffer (23296-23551/#FB00-#FBFF)
; This area is used for many purposes:
; - buffer of 256 bytes of a directory sector;
; - buffer of disk configuration sector;
; - #AA flag is placed at BUFFER by RESET08 to execute 'RUN "boot"' command.
;==============================================================================
BUFFER      equ 23296   ;#5B00-#5BFF

;==============================================================================
; BASIC System Variables
; Only variables used by Beta DOS ROM are listed here. Comments about these 
;variables were taken from 'SPECTRUM 128 ROM 0 DISASSEMBLY' by Matthew Wilson, 
;Andrew Owen, Geoff Wearmouth, Rui Tunes and Paul Farrow, available at http://
;www.fruitcake.plus.com/Sinclair/Spectrum128 /ROMDisassemblySpectrum128ROMDisas
;sembly.htm (retrieved at May/05/2016).
;==============================================================================
; Used in reading the keyboard.
; Note: first byte is used by NMI01 to save disk type ID (CS_DTYPE), thus its 
;value is not saved by Magic Button.
KSTATE      equ 23552   ;#5C00-#5C07

; Stores newly pressed key.
LASTK       equ 23560   ;#5C08

; Time (in 50ths of a second) that a key must be held down before it repeats. 
;This starts off at 35.
REPDEL      equ 23561   ;#5C09

; Delay (in 50ths of a second) between successive repeats of a key held down
; - initially 5.
REPPER      equ 23562   ;#5C0A

; Addresses of channels attached to streams.
STRMS       equ 23568   ;#5C10

; 256 less than address of character set, which starts with ' ' and carries on 
;to '(c)'.
CHARS       equ 23606   ;#5C36-#5C37

; Length of warning buzz.
RASP        equ 23608   ;#5C38

; Length of keyboard click.
PIP         equ 23609   ;#5C39

; 1 less than the report code. Starts off at 255 (for -1) so 'PEEK 23610' gives 
;255.
ERR_NR      equ 23610   ;#5C3A

; Various flags to control the BASIC system:
;   Bit 0: 1=Suppress leading space.
;   Bit 1: 1=Using printer, 0=Using screen.
;   Bit 2: 1=Print in L-Mode, 0=Print in K-Mode.
;   Bit 3: 1=L-Mode, 0=K-Mode.
;   Bit 4: 1=128K Mode, 0=48K Mode. [Always 0 on 48K Spectrum]
;   Bit 5: 1=New key press code available in LAST_K.
;   Bit 6: 1=Numeric variable, 0=String variable.
;   Bit 7: 1=Line execution, 0=Syntax checking.
FLAGS       equ 23611   ;#5C3B, iy+1

; Flags associated with the TV:
;   Bit 0  : 1=Using lower editing area, 0=Using main screen.
;   Bit 1-2: Not used (always 0).
;   Bit 3  : 1=Mode might have changed.
;   Bit 4  : 1=Automatic listing in main screen, 0=Ordinary listing in main 
;            screen.
;   Bit 5  : 1=Lower screen requires clearing after a key press.
;   Bit 6  : 1=Tape Loader option selected (set but never tested). [Always 0 on 
;            48K Spectrum]
;   Bit 7  : Not used (always 0).
TVFLAG      equ 23612   ;#5C3C, iy+2

; Address of item on machine stack to be used as error return.
ERR_SP      equ 23613   ;#5C3D-#5C3E, iy+3

; Line to be jumped to.
NEWPPC      equ 23618   ;#5C42-#5C43

; Statement number in line to be jumped to.
NSPPC       equ 23620   ;#5C44

;Border colour multiplied by 8; also contains the attributes normally used for 
;the lower half.
BORDCR      equ 23624   ;#5C48

; Address of variables.
VARS        equ 23627   ;#5C4B-#5C4C

; Address of channel data.
CHANS       equ 23631   ;#5C4F-#5C50

; Address of information currently being used for input and output.
CURCHL      equ 23633   ;#5C51-#5C52

; Address of BASIC program.
PROG        equ 23635   ;#5C53-#5C54

; Address of terminator of last DATA item.
DATADD      equ 23639   ;#5C57-#5C58

; Address of command being typed in.
E_LINE      equ 23641   ;#5C59-#5C5A

; Address of cursor.
K_CUR       equ 23643   ;#5C5B-#5C5C

; Address of the next character to be interpreted - the character after the 
;argument of PEEK,or the NEWLINE at the end of a POKE statement.
CH_ADD      equ 23645   ;#5C5D-#5C5E

; Address of temporary work space.
WORKSP      equ 23649   ;#5C61-#5C62

; Address of bottom of calculator stack.
STKBOT      equ 23651   ;#5C63-#5C64

; Address of start of spare space.
STKEND      equ 23653   ;#5C65-#5C66

; The number of lines (including one blank line) in the lower part of the 
;screen.
DF_SZ       equ 23659   ;#5C6B

; Address of first user-defined graphic. Can be changed to save space by having 
;fewer user-defined characters.
UDG         equ 23675   ;#5C7B-#5C7C

; Permanent current colours, etc, as set up by colour statements.
ATTR_P      equ 23693   ;#5C8D

; Temporary current colours (as set up by colour items).
ATTR_T      equ 23695   ;#5C8F

; Address of last byte of BASIC system area.
RAMTOP      equ 23730   ;#5CB2-#5CB3

; Address of last byte of physical RAM (65536/#FFFF for 48K; 32767/#7FFF for
;16K).
P_RAMT      equ 23732   ;#5CB4-#5CB5

;==============================================================================
; DOS System Variables
; These variables occupies 112 bytes located at #5CB6-#5D25 (23734-23845).
;==============================================================================
; This area is not really used by DOS and usually contains copy of channel 
;information area that have been moved by INITVARS subroutine, unless ZX 
;Interface 1 hadbeen initialized and extended system variables were created. 
;The first byte is #F4 (LSB of "K" channel output routine PRINT-OUT) or #00 
;(FLAGS3 of Interface 1 system variable).
CHANSCOPY   equ 23734   ;#5CB6-#5CC7

; Array of 4 bytes storing disktype for each drive (0-3 or "A"-"D"):
;   - bit 0: 0=40 tracks; 1=80 tracks (assigned by ID_TYPE);
;   - bit 1: 0=single side; 1=double side (assigned by ID_TYPE);
;   - bit 7: 0=40 tracks; 1=80 tracks (assigned by DS_40, DS_80 or SEL_DRIVE).
; #FF means unitialized variable (see INITVARS).
DSKTYPE     equ 23752   ;#5CC8-#5CCB

; ID of sector to be read from track 0 by READT0SX subroutine.
TRK0SECT    equ 23756   ;#5CCC

; Flag, stores bit 7 of FDC status register (port 31). #00=FDC is ready; 
;#80=FDC is busy.
NOTREADY    equ 23757   ;#5CCD
    
; Flag: #00=read from disk; #FF=write to disk.
FLAGRW      equ 23758   ;#5CCE

; Address of reserved area in the BASIC workspace.
WKSPADD     equ 23759   ;#5CCF-#5CD0

; READTRACK flag: #FF=ignore no disk error.
; SAVE: auto-start line number when saving a BASIC program.
; MOVE: store temporarily number of sectors of a file to move.
NODISK      equ 23761   ;#5CD1

; Name of BASIC variable. Note: this is not the ASCII code of variable name.
;Bits 0-4 define letter (%00000="A" to %11001="Z") and bits 5-7 define its type 
;(%100=numeric array; %110=character array).
VARNAME     equ 23762   ;#5CD2

; Number of sectors of a file that will be moved.
NSECMOV     equ 23763   ;#5CD3

; Directory entry position (0-127) of an erased file.
ERASEDFL    equ 23764   ;#5CD4

; Start sector ID of an erased file. The next DOS system variable CODEARG holds 
;ID of start track.
ERASEDSC    equ 23765   ;#5CD5

; Number of command line arguments given to LOAD <n$>CODE:
;   0=no argument (LOAD <n$>CODE) or statement is not LOAD,
;   1=one arguments (LOAD <n$>CODE <address>),
;   3=two arguments (LOAD <n$>CODE <address>,<length>).
;Also used to count number of errors of formatted disk (see DS_FORMAT) or to 
;store track ID of an erased file (see DS_MOVE).
CODEARG     equ 23766   ;#5CD6

;------------------------------------------------------------------------------
; General purpose variables used by several routines.
;------------------------------------------------------------------------------
VAR_A       equ 23767   ;#5CD7-#5CD8
VAR_A_L     equ VAR_A       
VAR_A_H     equ VAR_A+1
;
VAR_B       equ 23769   ;#5CD9-#5CDA
VAR_B_L     equ VAR_B
VAR_B_H     equ VAR_B+1
;
VAR_C       equ 23771   ;#5CDB-#5CDC
VAR_C_L     equ VAR_C
VAR_C_H     equ VAR_C+1

;------------------------------------------------------------------------------
; Next area stores one directory entry (16 bytes).
;------------------------------------------------------------------------------
; String of 8 bytes with the filename. This is also used to store disk label 
;during execution of FORMAT statement.
FILENAME    equ 23773   ;#5CDD, offset=+0

; One character specifying type of the file, 'B'=BASIC; 'C'=CODE; 'D'=DATA; 
;'#'=stream file
FILETYPE    equ 23781   ;#5CE5, offset=+8

; Parameter 1 (2-byte integer):
;   - BASIC=length of BASIC program + variables;
;   - CODE=start address or SP register value (for files saved by NMI);
;   - DATA=start address of array data (not used);
;   - #=first byte is number of part of multiple stream files and second byte
;       is always #20/32.
FILEPARM1   equ 23782   ;#5CE6-#5CE7, offset=+9

; Parameter 2 (2-byte integer):
;   - BASIC=length of BASIC program without variables;
;   - CODE/DATA/#=length of file data.
FILEPARM2   equ 23784   ;#5CE8-#5CE9, offset=+11

; Number of sectors occupied by file (1-byte integer).
FILESIZE    equ 23786   ;#5CEA, offset=+13

; First logical sector of the file (0-15).
FILESECT    equ 23787   ;#5CEB, offset=+14

; First logical track of the file.
FILETRACK   equ 23788   ;#5CEC, offset=+15
;------------------------------------------------------------------------------

; Save temporarily DOS systema variables FILEPARM1 to FILETRACK. Used to hold 
;entry info of source file during copy operation.
;       variable    offset    address
;       FILEPARM1     +0    #5CED/23788
;       FILEPARM2     +2    #5CEF/23790
;       FILESIZE      +4    #5CF1/23792
;       FILESECT      +5    #5CF2/23793
;       FILETRACK     +6    #5CF3/23794 
FILETEMP    equ 23789   ;#5CED-#5CF3

; Logical sector ID (0-15) for read/write operation.
RWSECID     equ 23796   ;#5CF4

; Logical track ID for read/write operation.
RWTRKID     equ 23797   ;#5CF5

; ID of current drive (0-3, corresponding to drives A-D).
CURRDRIVE   equ 23798   ;#5CF6

; Not used, its value is always 0. Any other value causes FT_STEPRT and 
;FT_DSKTYPE subroutines return erroneous results.
ZEROVAR     equ 23799   ;#5CF7

; Drive ID (0-4) with source file for copy or renaming operation.
SRCDRIVE    equ 23800   ;#5CF8

; Destination drive ID (0-4) for file copy operation.
DESTDRIVE   equ 23801   ;#5CF9

; Array of 4 bytes with stepping motor rate for each drive (0-3 or 'A'-'D'). 
;They hold #FF flag until real values are measured by SCAN_SRATE subroutine.
STEP_RATE   equ 23802   ;#5CFA-#5CFD

; Command to be sent to FDC during sector reading/writing: #88='READ SECTOR',
;#A8='WRITE SECTOR'. Used by RDWRSECT subroutine.
RW_CMD      equ 23806   ;#5CFE

; Temporary place to save start sector number where reading/writing operation
;will be done. Sector number is saved by SAV_STARTS subroutine.
STARTSECT   equ 23807   ;#5CFF

; Temporary place to save address of memory where reading/writing operation 
;will be done. Address saving is done by SAV_RWADD subroutine.
RWADDRESS   equ 23808   ;#5D00-#5D01

; Content of HL register pair is temporarily stored here before a call for
;BASIC routine.
HLTEMP      equ 23810   ;#5D02-#5D03

; Content of DE register pair is temporarily stored here before a call for
;BASIC routine.
DETEMP      equ 23812   ;#5D04-#5D05

; Number of bytes of directory entry to be compared with argument of a 
;statement in the command line. Most usual value is 9, to compare filename
;and file type (B, C, D or #). One additional byte is compared in stream type 
;files, matching number of part of multiple segment of a stream (when a stream
;segment data grows above 4096 bytes, a new segment file is created).
CMP_SIZE    equ 23814   ;#5D06

; Flag: 0=file does not exist.
NOFILE      equ 23815   ;#5D07

; Temporary place to save first character of a filename.
FSTCHAR     equ 23816   ;#5D08

; Access mode of an opened stream file: 'R' (read mode), 'W' (write mode) or
;'RND' (random access mode).
OPENMODE    equ 23817   ;#5D09

; Not used.
; 23818/#5D0A-23819/#5D0B

; Flag: 0=disk configuration data in printer buffer will be saved before a
;         character being printed by PRNCHR01 subroutine.
SV_DCFG     equ 23820   ;#5D0C

; Directory entry position (0-127) of the file being copied to another disk.
SRC_ENTR    equ 23821   ;#5D0D

; Flag: #FF=workspace and calculator stack will not be cleared after statement 
;           execution;
;       #FE=PRINTERR does not print message.
CLR_WSP     equ 23822   ;#5D0E

; DOS error code.
D_ERRCOD    equ 23823   ;#5D0F

; Used by DS_LOAD, DS_PEEK and DS_POKE to define what statement to execute:
;       #00=executing LOAD statement
;       #FF=executing PEEK statement
;       #EE=executing POKE statement
; Also used by EXEC_BAS when BASIC program is loaded: 0=auto start BASIC.
LDPKEXEC    equ 23824   ;#5D10

; Start address of statement to be interpreted by DOS.
DSTMADDR    equ 23825   ;#5D11-#5D12

; Old value of ERR_SP is saved here.
ERRSPTMP    equ 23827   ;#5D13-#5D14

; Mode of DOS interpreter: #00=command line interface, #FF=BASIC interpreter.
DOSMODE     equ 23829   ;#5D15

; The value written into port 255 (secondary configuration register) cannot be
;read back. Each OUT for this port has its value saved into this variable.
PORT255     equ 23830   ;#5D16

; Track 0/sector 9 is used to save contents of printer buffer that will be
;destroyed by DOS operation. This flag defines whether printer buffer should be
;saved or loaded. It is also used for other purposes.
;   - Non zero value: printer buffer should be saved before being overwritten.
;   - 0: load printer buffer contents after executing DOS statement.
;   - #AA: do not initialize DOS system variables (see INITDOS subroutine).
;   - #AA: do not print logo at command line interface.
FLAGBUFF    equ 23831   ;#5D17

; ZX Interface 1 creates extended system variables at 23734-.
; Flag: #00=ZX Interface 1 isn't connected; #FF=Interface 1 is present and its
;system variables must be preserved.
; Flag: #00=do not swap set of DOS system variables with set of ZX Interface 1 
;extended BASIC system variables.
IF1VAR      equ 23832   ;#5D18

; Number of current drive (0=A, 1=B, 2=C, 3=D).
DEFLTDRV    equ 23833   ;#5D19

; Return address after end of DOS statement execution.
DOS_RET     equ 23834   ;#5D1A-#5D1B

; Old value of stack pointer.
OLDSP       equ 23836   ;#5D1C-#5D1D

; Position of file entry in the directory (0-127).
FILEPOS     equ 23838   ;#5D1E

; Flag: nonzero value means any 6 byte binary representation of floating point
;number, created during syntax checking, must be deleted.
RM_FPC      equ 23839   ;#5D1F

; Temporary space to store 3 bytes of line editor memory.
ELINE_T     equ 23840   ;#5D20-#5D22

; Size (number of sectors) of a buffer created into workspace (1-16).
WSBUFFSIZ   equ 23843   ;#5D23

; Not used.
; 23844/#5D24-23845#5D25

;==============================================================================

;##############################################################################
; Additional infos
;##############################################################################

;==============================================================================
; Error codes
;==============================================================================
;------------------------------------------------------------------------------
; DOS error codes
; DOS stores error code in D_ERRCOD system variable or in BC register pair as 
;return value for 'USR 15363' BASIC function.
;------------------------------------------------------------------------------
;   Code        Description
;   ----        -----------
;     0         No error
;     1         File not found
;     2         File already exists
;     3         No space in disk (but erroneously raised by COPYFILE)
;     4         Directory full
;     5         Record number overflow
;     6         No disk in drive
;     7         Disk error
;    10         Stream already opened
;    11         Attempt to close a stream that is not a disk file (type "#")
;    12         Syntax error/BREAK key pressed
;    20         BREAK key pressed
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; BASIC error codes
; Code is in -1 (255) to 26 range and is stored in (ERR_NR) system variable.
;------------------------------------------------------------------------------
;   Code        Message
;   ----        -------
;    -1         0 - OK
;     0         1 - NEXT without FOR
;     1         2 - Variable not found
;     2         3 - Subscript wrong
;     3         4 - Out of memory
;     4         5 - Out of screen
;     5         6 - Number too big
;     6         7 - RETURN without GO SUB
;     7         8 - End of file
;     8         9 - STOP statement
;     9         A - Invalid argument
;    10         B - Integer out of range
;    11         C - Nonsense in BASIC
;    12         D - BREAK - CONT repeats
;    13         E - Out of DATA
;    14         F - Invalid file name
;    15         G - No room for line
;    16         H - STOP in INPUT
;    17         I - FOR without NEXT
;    18         J - Invalid I/O device
;    19         K - Invalid colour
;    20         L - BREAK into program
;    21         M - RAMTOP no good
;    22         N - Statement lost
;    23         O - Invalid Stream
;    24         P - FN without DEF
;    25         Q - Parameter error
;    26         R - Tape loading error
;------------------------------------------------------------------------------

;==============================================================================
; I/O ports used by CAS interface
; -------------------------------
; Communication with computer and interface is made by 6 I/O ports; among them,
;4 ports give access to FDC (Floppy Disk Controller) registers and 2 ports are
;for interface configuration. Except the write-only port 252, these ports are 
;disabled when computer is operating in BASIC mode to avoid clash with another 
;peripherals. They are enabled when DOS takes over control of computer, while 
;I/O operation at rear expansion connector of interface is inhibited.
;==============================================================================
;------------------------------------------------------------------------------
; Input ports 
; Data flow from Beta interface to computer.
;------------------------------------------------------------------------------
; Port      Description
; ----      -----------
;#1F/31     FDC status register
;#3F/63     FDC track register
;#5F/95     FDC sector register
;#7F/127    FDC data register
;#FF/255    some FDC signals
;               bit 0-5: unused
;               bit 6: DRQ signal (1=data is available for READ operation or
;                      data is expected for WRITE operation)
;               bit 7: INTRQ signal (1=command is finished; 0=command is in
;                      progress)
;
;------------------------------------------------------------------------------
; Output ports 
; Data flow from computer to Beta interface.
;------------------------------------------------------------------------------
; Port      Description
; ----      -----------
;#1F/31     FDC command register
;#3F/63     FDC track register
;#5F/95     FDC sector register
;#7F/127    FDC data register
;#FC/252    interface configuration register (write-only and never disabled)
;           Note 1: port address is even, thus it alters Spectrum ULA status
;           Note 2: bits 6-7 can disable CAS interface totally; this can be 
;                   achieved in BASIC with 'OUT 252,192+border' (border=0-7)
;               bit 0-2: screen border colour (%000-%111)
;               bit 3: sound output
;               bit 4: MIC output
;               bit 5: unused
;               bit 6: 0=DOS ROM is visible at 15360-15615/#3C00-#3CFF area
;                      1=BASIC ROM occupies that area
;               bit 7: 0=enable I/O operation with CAS and disable access of
;                        peripheral at rear expansion connector
;                      1=enable I/O operation with peripheral attached to CAS
;                        expansion connector and disable disk interface I/O
;                        ports                       
;#FF/255    secondary configuration register (write-only)
;               bit 0-1: drive select (%00='A'; %01='B'; %10='C'; %11='D')
;               bit 2: /MASTER RESET pin of FDC, must be kept high
;               bit 3: /HLT pin of FDC (1=head is loaded), must be kept high
;               bit 4: SIDE SELECT pin of drive (1=side 0, 0=side 1)
;               bit 5: unused
;               bit 6: DDEN pin of FDC (1=single density/FM, 0=double density/
;                      MFM)
;               bit 7: select pages 0-1 ROM (0=DOS ROM, 1=BASIC ROM)
;==============================================================================

;==============================================================================
; Format of Beta diskette
; -----------------------
; This section is based on Claus Jahn webpage (http://www.zx-modules.de/ 
;retrieved on Apr/03/2016) with minor corrections. Informations about stream 
;are based on M. James's book 'Guia Avançado para o Spectrum' (Portuguese 
;translation of 'An Expert Guide to the Spectrum'). 
;==============================================================================
; Sides, tracks and sectors
; -------------------------
; A disk has 1 or 2 sides, numbered as 0-1.
; Each disk surface has 40 or 80 concentric physical tracks, numbered in the 
;range 0-39 or 0-79. For single sided disk, the track number accepted by DOS 
;(logical track number) has the same value of the physical track number. For 
;double sided disk, logical track numbers are distributed in alternating sides 
;of disk, with even track number recorded on side 0 and odd track number on 
;side 1 (the algorithm to convert logical track ID to physical track ID is 
;explained in PHYSTRACK subroutine).
; Each track has 16 physical sectors numbered in the range 1-16. They aren't 
;recorded sequentially in the disk (sector interleaving) to improve data 
;transfer rate. Sector are numbered by DOS (logical sectors) into the range
;0-15; thus, this value must by increased by 1 before feeding the FDC track 
;register.
; Each sector is composed by 256 bytes of data; this is the smallest amount of
;information writeable to/readable from disk. When 1000 bytes (#03E8) is saved 
;with SAVE <n$>CODE statement, actually 1024 bytes (#0400) are sent to disk
;because they fit 4 sectors. In this example, the extra 24 bytes at file end
;could overwrite data in memory during loading, with undesirable effects; 
;this is avoided by DOS by copying only the necessary number of bytes to RAM 
;(see LASTSECTOR subroutine). 
; There are 4 different formats for Beta disks:
;   Format    Sides   Tracks  Sectors     Total Capacity  Avail. Space
;   ------    -----   ------  -------     --------------  ------------
;   SS/40       1        40      640         163840          159744
;   SS/80       1        80     1280         327680          323584
;   DS/40       2        80     1280         327680          323584
;   DS/80       2       160     2560         655360          651264
;Where: SS=single sided, DS=double sided, 40=40 tracks or sigle density, 80=80 
;tracks or double density. Available space is smaller than total disk capacity
;because part of disk (track 0) is used by DOS and not available for user
;files.
; DOS addresses a sector of disk with a pair of bytes: logical sector ID and 
;logical track ID. During a sequential read/write of a file, logical sector is
;increased until it exceeds 15; then, sector is reset to 0 and next track is 
;selected, incrementing logical track number. Usually this pair of bytes is 
;stored in the memory or disk following the sequence sector/track; thus, it is
;recovered by Z80 register pair with least significant byte (LSB) as the sector 
;ID and most significant byte (MSB) as the track ID.
;
; Data in the disk
; ----------------
;   Track 0
;   -------
;   The first track of disk is used to store file system information and is 
;   not directly available to store user files. Its 16 sectors have following 
;   functions:
;       - sectors 0-7 hold the disk directory;
;       - sector 8 holds disk info (configuration sector);
;       - sector 9 is where printer buffer is saved during disk operation;
;       - sector 10 is where the first 256 bytes of RAM (#4000/16384-#40FF/
;         16639) are saved during magic button operation (see NMI routine);
;       - sectors 11-15 aren't used and are filled with 0s.
;       Directory
;       ---------
;       The 2048 bytes (8 sectors) of directory area can hold up to 128 entries
;       with length　of 16 bytes each. Directory entries are numbered in 0-127 
;       range.
;       A directory entry describes one file and contains following fields:
;           - filename (8 bytes);
;           - type of file (1 byte, where "B"=BASIC, "C"=CODE, "D"=DATA and 
;                           "#"=stream file);
;           - parameter 1 (2 bytes, see below);
;           - parameter 2 (2 bytes, see below);
;           - number of sectors occupied by the file (1 byte);
;           - start logical sector ID (1 byte; ID=0-15);
;           - start logical track ID (1 byte; ID=0-159 for DS/80 disk).
;       Type of files
;       -------------
;           BASIC
;           -----
;           This file stores BASIC program lines and variables. Parameter 1
;           is the length of BASIC program and variables and parameter 2 is
;           the length of program only. The file body (see below) contains
;           auto-execution line number.
;           CODE
;           ----
;           This file contains a sequence of bytes saved from memory. Parameter 
;           1 is start address and parameter 2 is length of code. File saved by
;           NMI (Magic Button) routine is different, it has SP register saved 
;           in parameter 1 instead. 
;           DATA
;           ----
;           This file contains an character ou numeric array. Parameter 1 is 
;           not used (start address of array data when it was saved) and 
;           Parameter 2 is length of data array.
;           Stream (type #)
;           ---------------
;           Stream is a software layer of Sinclair BASIC that provides device
;           independent input/output operation. Once openned with 'OPEN #s' 
;           (s=4-15), a stream can be written with 'PRINT #s' or read by 
;           'INPUT #s' and 'INKEY$#s' BASIC statements. Beta DOS provides file
;           that can be assigned to be a stream and used as such. During write
;           operation, stream data can grow its size up to 4096 bytes; further
;           writing will create a new file (segment) with same name and type,
;           but with different segment number. The disk will be filled with as
;           many segments as neccessary to store all data, splitted in blocks
;           with up to 4096 bytes of length each. The first byte of parameter 1 
;           (LSB) is the ID number of the segment from a set of stream files 
;           sharing the same filename; the second byte (MSB) is not used and is
;           always #20/32. Parameter 2 is the data length (1-4096 bytes).
;       Configuration Sector (track 0, sector 8)
;       ----------------------------------------
;           Sector  Label       Description
;           ------  -----       -----------
;              0    CS_DEND     End of directory marker (0).
;            1-224              Unused, filled with 0.
;             225   CS_FREES    First free logical sector ID (0-15).
;             226   CS_FREET    First free logical track ID (1-159 for DS/80).
;             227   CS_DTYPE    Disk type:
;                                   22/#16/%00010110=DS/80; 
;                                   23/#17/%00010111=DS/40; 
;                                   24/#18/%00011000=SS/80; 
;                                   25/#19/%00011001=SS/40.
;             228   CS_NFILE    Total count of files in the disk, including 
;                               erased ones.
;           229-230 CS_NFREE    Number of free sectors.
;             231   CS_IDENT    ID of BETA disk (#10/16).
;           232-233             Unused, filled with 0.
;           234-242             Unused, filled with space (#20/32).
;             243               Unused, filled with 0.
;             244   CS_ERASF    Number of erased files.
;           245-252 CS_LABEL    Disk label (8 characters).
;           253-255             Unused, filled with 0.
;           Note: these labels are available as sector offset (see 'Labels').
;   File body
;   ---------
;       Data of a file are written sequentially in the disk, sector by sector, 
;       starting from the logical track 1 and logical sector 0. BASIC files 
;       store some info at the end of data block. 
;       BASIC
;       -----
;           At offset=(file length): markers #80/128 and #AA/170;
;           at offset=(length+2): autostart line (0-9999).
;
;==============================================================================

;==============================================================================
; Streams and channels
; --------------------
; This section is based on M. James's book 'Guia Avançado para o Spectrum' 
;(Portuguese translation of 'An Expert Guide to the Spectrum'), Tony Baker's
;series 'Streams and Channels' published in ZX Computing December 1986 to April 
;1987 issues and Clóvis Friolani revision of 'CBI-95 Manual de Operação'.
;------------------------------------------------------------------------------
; Unexpanded Spectrum/TK90X has to deal with few peripherals so there are not
;many BASIC statements devoted for I/O operations. When characters and texts 
;are exchanged between computer and peripherals, PRINT (for screen output) and 
;INPUT (for keyboard input) are usually employed. When an add-on is attached, a 
;new statements become neccessary, e.g. LPRINT for a printer. Nevertheless, 
;there is no pratical way to extend BASIC for each new kind of add-on that is 
;invented. Use of specific statements turns also program too tied to a narrow 
;range of devices. Although this fact is not widely known, Sinclair BASIC 
;already provides some device independence. Its I/O is splitted in two parts: 
;stream is the programming side and channel is the hardware side.
; Stream is a generic way to address device in a program. For example, 'PRINT 
;#0' directs printing to the lower lines of the screen, 'PRINT #2' to the main 
;screen window and 'PRINT #3' to the printer. The number after '#' selects what
;stream printing is directed to. It is also possible to get data from a stream, 
;e.g. with 'INPUT #2;a$'.
; Channel is a machine code program that provides communication with a specific
;hardware and is identified by a single letter string. Unexpanded computer has 
;the following channels:
; Channel   Output                      Input
; -------   ------                      -----
;   "K"     lower lines of screen       keyboard
;   "S"     main screen window          none
;   "P"     printer                     none
;   "R"     BASIC line editor area      none
;To be useful, a channel must be associated to a stream with 'OPEN #'. Typing 
;'OPEN #4,"K"' in BASIC command line followed by 'enter' will make such 
;association, i.e. it will open the stream 4. Once opened, output is done with 
;statements like 'PRINT #4;"abc"'or input with 'INPUT #4;a$'. This association 
;can be undone, i.e. a stream can be close with 'CLOSE #4' and further attempt 
;to do I/O operation with this stream will result in error. Sinclair BASIC has 
;16 streams numbered as 0-15 (actually there are more 3 hidden streams, -3/#FD, 
;-2/#FE and -1/#FF, but they are not accessible from BASIC). By default, 
;streams 0 and 1 are opened with channel "K", stream 2 with channel "S" and 
;stream 3 with channel "P". Only streams 4-15 are free for user programs.
;
; Use of stream and channel in Beta DOS
; -------------------------------------
; Beta DOS allows a disk file (stream file) to be associated to the "D" channel 
;with 'OPEN #' DOS statement (note: unlike BASIC statement, USR 15363 is 
;required). For example, in the following program, a new stream file is created 
;in disk when is opened in sequential write access mode; later, data can be 
;written to this file with PRINT #:
;
;   10 RANDOMIZE USR 15363 : REM : OPEN #4;"streamfl"W
;   20 PRINT #4;16*16
;   30 PRINT #4;"16*16"
;   40 PRINT #4;1'2'3'"String"
;   50 RANDOMIZE USR 15363 : REM : CLOSE #4
;
;The file with name "streamfl" and type "#" is created in the disk. This type
;of file is always created with size of 16 sectors (4096 bytes) and it is 
;empty, so size of data (file parameter 2, see 'Format of Beta diskette') is 0 
;and channel cursor is pointing to the start of the file. The argument of PRINT 
;is evaluated by BASIC monitor before being written in disk. Thus, line 20 of 
;example above will produce the output "2", "5", "6" and #0D because was a 
;numeric argument, but line 30 will give the string "16*16" and #0D. End of
;record is marked with 13/#0D character (enter) which is generated by the end
;of PRINT statement or by "'" (apostrophe) separator as in the line 40. Each 
;character is stored in a buffer (channel buffer) and, when it is full, the 
;entire sector is written into disk. When data size exceeds 4096 bytes, a new 
;file with same name and type are created in disk, but with different file 
;parameter 1. Thus, a stream can be composed by one or more 4096-byte segments 
;(files). To terminate an association of a stream to a file, it must be closed 
;with DOS statement 'CLOSE #'. Any data remaining in the channel buffer is 
;saved before a stream is closed, thus it is advisible to close all stream 
;files  before turning off or resetting computer to prevent data loss.
; Sequential file opened in write mode can only acept characters from programs.
;To read data stored in "#" type file, it must be opened afterwards in read 
;mode, e.g.:
;
;   10 RANDOMIZE USR 15363 : REM : OPEN #4,"streamfl"R
;   20 INPUT #4;a
;   30 INPUT #4;b
;   40 INPUT #4;a$;b$;c$;d$
;   50 RANDOMIZE USR 15363 : REM : CLOSE #4
;
;INPUT statement will expect data from stream in the same way as it would 
;expect from a user typing in the keyboard. Thus, data is received character by 
;character and input is finished when 'enter' character is found; all collected
;characters then is assigned to variable present the in command line. In the 
;above listing, line 20 will assign numeric value 256 to the 'a' variable.
;Surprisingly, line 30 will assign the same value to variable b; this occurs 
;because BASIC will interpret the string "16*16" as numeric expression since 
;variable of INPUT is numeric type. Line 40 shows how to read several variables 
;with one INPUT using ";" separator.
; The third open mode of channel is random access mode; for example:
;   RANDOMIZE USER 15363 : REM : OPEN #4,"rndfile"RND,15
;will create a new "#" type file in disk. The numeric parameter after RND token
;is the length of record (15 characters in the example). Random access file has
;fixed length records (sequential files has variable length records, separated
;by 'enter'). Record is stored as string; if its length is shorter than record
;size, the string is stored with 'enter' (#0D/13) at its end. When string is
;longer than the record, it is truncated to fit record size and 'enter' is 
;ommited. Unlike sequential file, when a stream file is opened in random access 
;mode, both write and read operations can be done without closing the file. 
;Record number must be given when writing/reading data in random mode:
;   PRINT#4;(5),"BC548 transistor"  (write a string in the record 5);
;   INPUT#4;(17),b                  (read a numeric value from record 17).
;A limit of one record for each write (PRINT#) or read (INPUT#) operation must
;be observed.
;
; Details about stream and channels
; ----------------------------------
; Every channel uses a portion of memory called "channel information block" to
;store data and variables, stored in the "Channel Information Area" of memory
;used by BASIC monitor. This area starts from address pointed by CHANS system
;variable and ends one byte before BASIC program area (pointed by PROG). The
;channels "K", "S" and "P" are very simple, channel info block has only 5 bytes
;and is composed by 3 fields:
;bytes 0-1: output routine address (PRINT# is redirected here);
;bytes 2-3: input routine address (INPUT# is redirected here);
;byte 4: name of channel ("K", "S" or "P").
;The structure of channel "D" is more complex, including variables and data of
;opened file and a buffer to store one sector of disk. It occupies 292 bytes,
;thus it is neccessary to check whether there are enough RAM before opening 
;one or more stream files. 
; STRMS system variable stores data of each 19 streams present in the Sinclair 
;BASIC, from stream -3 (#FD) to stream 15. A stream is described by 2-bytes
;value in STRMS, thus stream -3 data is at STRMS, stream -2 at STRMS+2 and so
;on. The first stream accessible by BASIC is 0 and its data is at STRMS+6. 
;Closed stream data is #0000, non-zero value corresponds to an opened stream
;whose channel info block address is calculated by: (CHANS)+(stream data)-1.
;CURCHL system variable stores address of current channel, so this calculation
;is not needed for user programs.
;
;------------------------------------------------------------------------------
; Structure of "D" channel information block 
;------------------------------------------------------------------------------
; Offset    Field           Description
; ------    -------         -----------
;  0-1      CH_OUTR         Output routine address (CH_OUTPUT)
;  2-3      CH_INPR         Input routine address (CH_INPUT)
;   4       CH_NAME         Name of channel ("D")
;  5-6      CH_IF1O         Not used, field for ZX Interface 1 channels
;  7-8      CH_IF1I         Not used, field for ZX Interface 1 channels
;  9-10     CH_BLEN         Length of channel info block (#0124/292 bytes)
;   11      CH_DRIV         Drive that holds the stream file (0-3)
;   12      CH_ENTR         Position of file entry in the directory (0-127)
;  13-14    CH_DCUR         Position of stream data cursor
;   15      CH_MODE         Access mode: #00=read, #7F=random and #FF=write
;  16-23    CH_FNAM         Filename of stream file
;   24      CH_FTYP         Type of file ("#")
;   25      CH_SGMT         ID of current segment of file, LSB of fileparm1
;   26      CH_SPAC         MSB of fileparm1, it is always #20/32
;  27-28    CH_FPR2         Parameter 2, length of data in current segment
;   29      CH_FSIZ         Number of sectors occupied by stream file (16)
;   30      CH_FSEC         Start sector ID of stream file segment
;   31      CH_FTRK         Start track ID of stream file segment
;   32      CH_RLEN         Record length (1-256)
;   33      CH_WCUR         Cursor position in workspace or number of 
;                           characters sent to record
;   34      CH_WREC         Flag, 0=waiting for record number argument
;   35      CH_FLSH         Flag, channel buffer must be written to disk
;  36-291   CH_BUFF         256-byte channel buffer
;
;==============================================================================

;##############################################################################
